summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoredwin <edwin@FreeBSD.org>2003-08-29 03:14:03 +0000
committeredwin <edwin@FreeBSD.org>2003-08-29 03:14:03 +0000
commit32bdf60426b15158f63d8fac3160221ebd1fe5eb (patch)
tree01634c3aed385d0bc17a4541ed57cf654158d9f4
parent400a9a28e925e2b0e6193058d162dd6c117c6c3d (diff)
downloadFreeBSD-ports-32bdf60426b15158f63d8fac3160221ebd1fe5eb.zip
FreeBSD-ports-32bdf60426b15158f63d8fac3160221ebd1fe5eb.tar.gz
FIXUP for possible remote DoS w/ scrub rules
http://www.openbsd.org/cgi-bin/cvsweb/src/sys/net/pf_norm.c?sortby=date PR: - Submitted by: mlaier@#bsdcode Obtained from: OpenBSD-Current
-rw-r--r--security/pf/Makefile2
-rw-r--r--security/pf/files/patch-ag383
2 files changed, 384 insertions, 1 deletions
diff --git a/security/pf/Makefile b/security/pf/Makefile
index 9aba498..c28667d 100644
--- a/security/pf/Makefile
+++ b/security/pf/Makefile
@@ -7,7 +7,7 @@
PORTNAME= pf_freebsd
PORTVERSION= 1.0
-PORTREVISION= 6
+PORTREVISION= 7
CATEGORIES= security ipv6
MASTER_SITES= http://pf4freebsd.love2party.net/
.if defined(WITH_ALTQ) && (${WITH_ALTQ} == "yes")
diff --git a/security/pf/files/patch-ag b/security/pf/files/patch-ag
new file mode 100644
index 0000000..ed4cd5d
--- /dev/null
+++ b/security/pf/files/patch-ag
@@ -0,0 +1,383 @@
+--- pf/pf_norm.c Fri Aug 29 03:31:24 2003
++++ pf/pf_norm.c Fri Aug 29 03:40:58 2003
+@@ -117,10 +117,10 @@
+ void pf_flush_fragments(void);
+ void pf_free_fragment(struct pf_fragment *);
+ struct pf_fragment *pf_find_fragment(struct ip *, struct pf_frag_tree *);
+-struct mbuf *pf_reassemble(struct mbuf **, struct pf_fragment *,
++struct mbuf *pf_reassemble(struct mbuf **, struct pf_fragment **,
+ struct pf_frent *, int);
+ struct mbuf *pf_fragcache(struct mbuf **, struct ip*,
+- struct pf_fragment *, int, int, int *);
++ struct pf_fragment **, int, int, int *);
+ u_int16_t pf_cksum_fixup(u_int16_t, u_int16_t, u_int16_t);
+ int pf_normalize_tcp(int, struct ifnet *, struct mbuf *,
+ int, int, void *, struct pf_pdesc *);
+@@ -385,7 +385,7 @@
+ }
+
+ struct mbuf *
+-pf_reassemble(struct mbuf **m0, struct pf_fragment *frag,
++pf_reassemble(struct mbuf **m0, struct pf_fragment **frag,
+ struct pf_frent *frent, int mff)
+ {
+ struct mbuf *m = *m0, *m2;
+@@ -397,10 +397,10 @@
+ u_int16_t max = ip->ip_len + off;
+
+ #if defined(__FreeBSD__)
+- KASSERT((frag == NULL || BUFFER_FRAGMENTS(frag)),
+- ("! (frag == NULL || BUFFER_FRAGMENTS(frag)): %s", __FUNCTION__));
++ KASSERT((*frag == NULL || BUFFER_FRAGMENTS(*frag)),
++ ("! (*frag == NULL || BUFFER_FRAGMENTS(*frag)): %s", __FUNCTION__));
+ #else
+- KASSERT(frag == NULL || BUFFER_FRAGMENTS(frag));
++ KASSERT(*frag == NULL || BUFFER_FRAGMENTS(*frag));
+ #endif
+
+ /* Strip off ip header */
+@@ -408,38 +408,38 @@
+ m->m_len -= hlen;
+
+ /* Create a new reassembly queue for this packet */
+- if (frag == NULL) {
++ if (*frag == NULL) {
+ #if defined(__FreeBSD__)
+- frag = uma_zalloc(pf_frag_pl, M_NOWAIT);
++ *frag = uma_zalloc(pf_frag_pl, M_NOWAIT);
+ #else
+- frag = pool_get(&pf_frag_pl, PR_NOWAIT);
++ *frag = pool_get(&pf_frag_pl, PR_NOWAIT);
+ #endif
+- if (frag == NULL) {
++ if (*frag == NULL) {
+ pf_flush_fragments();
+ #if defined(__FreeBSD__)
+- frag = uma_zalloc(pf_frag_pl, M_NOWAIT);
++ *frag = uma_zalloc(pf_frag_pl, M_NOWAIT);
+ #else
+- frag = pool_get(&pf_frag_pl, PR_NOWAIT);
++ *frag = pool_get(&pf_frag_pl, PR_NOWAIT);
+ #endif
+- if (frag == NULL)
++ if (*frag == NULL)
+ goto drop_fragment;
+ }
+
+- frag->fr_flags = 0;
+- frag->fr_max = 0;
+- frag->fr_src = frent->fr_ip->ip_src;
+- frag->fr_dst = frent->fr_ip->ip_dst;
+- frag->fr_p = frent->fr_ip->ip_p;
+- frag->fr_id = frent->fr_ip->ip_id;
++ (*frag)->fr_flags = 0;
++ (*frag)->fr_max = 0;
++ (*frag)->fr_src = frent->fr_ip->ip_src;
++ (*frag)->fr_dst = frent->fr_ip->ip_dst;
++ (*frag)->fr_p = frent->fr_ip->ip_p;
++ (*frag)->fr_id = frent->fr_ip->ip_id;
+ #if defined(__FreeBSD__)
+- frag->fr_timeout = time_second;
++ (*frag)->fr_timeout = time_second;
+ #else
+- frag->fr_timeout = time.tv_sec;
++ (*frag)->fr_timeout = time.tv_sec;
+ #endif
+- LIST_INIT(&frag->fr_queue);
++ LIST_INIT(&(*frag)->fr_queue);
+
+- RB_INSERT(pf_frag_tree, &pf_frag_tree, frag);
+- TAILQ_INSERT_HEAD(&pf_fragqueue, frag, frag_next);
++ RB_INSERT(pf_frag_tree, &pf_frag_tree, *frag);
++ TAILQ_INSERT_HEAD(&pf_fragqueue, *frag, frag_next);
+
+ /* We do not have a previous fragment */
+ frep = NULL;
+@@ -450,7 +450,7 @@
+ * Find a fragment after the current one:
+ * - off contains the real shifted offset.
+ */
+- LIST_FOREACH(frea, &frag->fr_queue, fr_next) {
++ LIST_FOREACH(frea, &(*frag)->fr_queue, fr_next) {
+ if (frea->fr_ip->ip_off > off)
+ break;
+ frep = frea;
+@@ -503,41 +503,41 @@
+
+ insert:
+ /* Update maximum data size */
+- if (frag->fr_max < max)
+- frag->fr_max = max;
++ if ((*frag)->fr_max < max)
++ (*frag)->fr_max = max;
+ /* This is the last segment */
+ if (!mff)
+- frag->fr_flags |= PFFRAG_SEENLAST;
++ (*frag)->fr_flags |= PFFRAG_SEENLAST;
+
+ if (frep == NULL)
+- LIST_INSERT_HEAD(&frag->fr_queue, frent, fr_next);
++ LIST_INSERT_HEAD(&(*frag)->fr_queue, frent, fr_next);
+ else
+ LIST_INSERT_AFTER(frep, frent, fr_next);
+
+ /* Check if we are completely reassembled */
+- if (!(frag->fr_flags & PFFRAG_SEENLAST))
++ if (!((*frag)->fr_flags & PFFRAG_SEENLAST))
+ return (NULL);
+
+ /* Check if we have all the data */
+ off = 0;
+- for (frep = LIST_FIRST(&frag->fr_queue); frep; frep = next) {
++ for (frep = LIST_FIRST(&(*frag)->fr_queue); frep; frep = next) {
+ next = LIST_NEXT(frep, fr_next);
+
+ off += frep->fr_ip->ip_len;
+- if (off < frag->fr_max &&
++ if (off < (*frag)->fr_max &&
+ (next == NULL || next->fr_ip->ip_off != off)) {
+ DPFPRINTF(("missing fragment at %d, next %d, max %d\n",
+ off, next == NULL ? -1 : next->fr_ip->ip_off,
+- frag->fr_max));
++ (*frag)->fr_max));
+ return (NULL);
+ }
+ }
+- DPFPRINTF(("%d < %d?\n", off, frag->fr_max));
+- if (off < frag->fr_max)
++ DPFPRINTF(("%d < %d?\n", off, (*frag)->fr_max));
++ if (off < (*frag)->fr_max)
+ return (NULL);
+
+ /* We have all the data */
+- frent = LIST_FIRST(&frag->fr_queue);
++ frent = LIST_FIRST(&(*frag)->fr_queue);
+ #if defined(__FreeBSD__)
+ KASSERT((frent != NULL), ("frent == NULL: %s", __FUNCTION__));
+ #else
+@@ -545,7 +545,8 @@
+ #endif
+ if ((frent->fr_ip->ip_hl << 2) + off > IP_MAXPACKET) {
+ DPFPRINTF(("drop: too big: %d\n", off));
+- pf_free_fragment(frag);
++ pf_free_fragment(*frag);
++ *frag = NULL;
+ return (NULL);
+ }
+ next = LIST_NEXT(frent, fr_next);
+@@ -575,11 +576,12 @@
+ m_cat(m, m2);
+ }
+
+- ip->ip_src = frag->fr_src;
+- ip->ip_dst = frag->fr_dst;
++ ip->ip_src = (*frag)->fr_src;
++ ip->ip_dst = (*frag)->fr_dst;
+
+ /* Remove from fragment queue */
+- pf_remove_fragment(frag);
++ pf_remove_fragment(*frag);
++ *frag = NULL;
+
+ hlen = ip->ip_hl << 2;
+ ip->ip_len = off + hlen;
+@@ -611,7 +613,7 @@
+ }
+
+ struct mbuf *
+-pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment *frag, int mff,
++pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
+ int drop, int *nomem)
+ {
+ struct mbuf *m = *m0;
+@@ -622,27 +624,27 @@
+ int hosed = 0;
+
+ #if defined(__FreeBSD__)
+- KASSERT((frag == NULL || !BUFFER_FRAGMENTS(frag)),
+- ("!(frag == NULL || !BUFFER_FRAGMENTS(frag)): %s", __FUNCTION__));
++ KASSERT((*frag == NULL || !BUFFER_FRAGMENTS(*frag)),
++ ("!(*frag == NULL || !BUFFER_FRAGMENTS(*frag)): %s", __FUNCTION__));
+ #else
+- KASSERT(frag == NULL || !BUFFER_FRAGMENTS(frag));
++ KASSERT(*frag == NULL || !BUFFER_FRAGMENTS(*frag));
+ #endif
+
+ /* Create a new range queue for this packet */
+- if (frag == NULL) {
++ if (*frag == NULL) {
+ #if defined(__FreeBSD__)
+- frag = uma_zalloc(pf_cache_pl, M_NOWAIT);
++ *frag = uma_zalloc(pf_cache_pl, M_NOWAIT);
+ #else
+- frag = pool_get(&pf_cache_pl, PR_NOWAIT);
++ *frag = pool_get(&pf_cache_pl, PR_NOWAIT);
+ #endif
+- if (frag == NULL) {
++ if (*frag == NULL) {
+ pf_flush_fragments();
+ #if defined(__FreeBSD__)
+- frag = uma_zalloc(pf_cache_pl, M_NOWAIT);
++ *frag = uma_zalloc(pf_cache_pl, M_NOWAIT);
+ #else
+- frag = pool_get(&pf_cache_pl, PR_NOWAIT);
++ *frag = pool_get(&pf_cache_pl, PR_NOWAIT);
+ #endif
+- if (frag == NULL)
++ if (*frag == NULL)
+ goto no_mem;
+ }
+
+@@ -654,33 +656,34 @@
+ #endif
+ if (cur == NULL) {
+ #if defined(__FreeBSD__)
+- uma_zfree(pf_cache_pl, frag);
++ uma_zfree(pf_cache_pl, *frag);
+ #else
+- pool_put(&pf_cache_pl, frag);
++ pool_put(&pf_cache_pl, *frag);
+ #endif
++ *frag = NULL;
+ goto no_mem;
+ }
+ pf_ncache++;
+
+- frag->fr_flags = PFFRAG_NOBUFFER;
+- frag->fr_max = 0;
+- frag->fr_src = h->ip_src;
+- frag->fr_dst = h->ip_dst;
+- frag->fr_p = h->ip_p;
+- frag->fr_id = h->ip_id;
++ (*frag)->fr_flags = PFFRAG_NOBUFFER;
++ (*frag)->fr_max = 0;
++ (*frag)->fr_src = h->ip_src;
++ (*frag)->fr_dst = h->ip_dst;
++ (*frag)->fr_p = h->ip_p;
++ (*frag)->fr_id = h->ip_id;
+ #if defined(__FreeBSD__)
+- frag->fr_timeout = time_second;
++ (*frag)->fr_timeout = time_second;
+ #else
+- frag->fr_timeout = time.tv_sec;
++ (*frag)->fr_timeout = time.tv_sec;
+ #endif
+
+ cur->fr_off = off;
+ cur->fr_end = max;
+- LIST_INIT(&frag->fr_cache);
+- LIST_INSERT_HEAD(&frag->fr_cache, cur, fr_next);
++ LIST_INIT(&(*frag)->fr_cache);
++ LIST_INSERT_HEAD(&(*frag)->fr_cache, cur, fr_next);
+
+- RB_INSERT(pf_frag_tree, &pf_cache_tree, frag);
+- TAILQ_INSERT_HEAD(&pf_cachequeue, frag, frag_next);
++ RB_INSERT(pf_frag_tree, &pf_cache_tree, *frag);
++ TAILQ_INSERT_HEAD(&pf_cachequeue, *frag, frag_next);
+
+ DPFPRINTF(("fragcache[%d]: new %d-%d\n", h->ip_id, off, max));
+
+@@ -692,7 +695,7 @@
+ * - off contains the real shifted offset.
+ */
+ frp = NULL;
+- LIST_FOREACH(fra, &frag->fr_cache, fr_next) {
++ LIST_FOREACH(fra, &(*frag)->fr_cache, fr_next) {
+ if (fra->fr_off > off)
+ break;
+ frp = fra;
+@@ -929,21 +932,22 @@
+
+ pass:
+ /* Update maximum data size */
+- if (frag->fr_max < max)
+- frag->fr_max = max;
++ if ((*frag)->fr_max < max)
++ (*frag)->fr_max = max;
+
+ /* This is the last segment */
+ if (!mff)
+- frag->fr_flags |= PFFRAG_SEENLAST;
++ (*frag)->fr_flags |= PFFRAG_SEENLAST;
+
+ /* Check if we are completely reassembled */
+- if ((frag->fr_flags & PFFRAG_SEENLAST) &&
+- LIST_FIRST(&frag->fr_cache)->fr_off == 0 &&
+- LIST_FIRST(&frag->fr_cache)->fr_end == frag->fr_max) {
++ if (((*frag)->fr_flags & PFFRAG_SEENLAST) &&
++ LIST_FIRST(&(*frag)->fr_cache)->fr_off == 0 &&
++ LIST_FIRST(&(*frag)->fr_cache)->fr_end == (*frag)->fr_max) {
+ /* Remove from fragment queue */
+ DPFPRINTF(("fragcache[%d]: done 0-%d\n", h->ip_id,
+- frag->fr_max));
+- pf_free_fragment(frag);
++ (*frag)->fr_max));
++ pf_free_fragment(*frag);
++ *frag = NULL;
+ }
+
+ return (m);
+@@ -952,8 +956,8 @@
+ *nomem = 1;
+
+ /* Still need to pay attention to !IP_MF */
+- if (!mff && frag)
+- frag->fr_flags |= PFFRAG_SEENLAST;
++ if (!mff && *frag != NULL)
++ (*frag)->fr_flags |= PFFRAG_SEENLAST;
+
+ m_freem(m);
+ return (NULL);
+@@ -961,15 +965,15 @@
+ drop_fragment:
+
+ /* Still need to pay attention to !IP_MF */
+- if (!mff && frag)
+- frag->fr_flags |= PFFRAG_SEENLAST;
++ if (!mff && *frag != NULL)
++ (*frag)->fr_flags |= PFFRAG_SEENLAST;
+
+ if (drop) {
+ /* This fragment has been deemed bad. Don't reass */
+- if ((frag->fr_flags & PFFRAG_DROP) == 0)
++ if (((*frag)->fr_flags & PFFRAG_DROP) == 0)
+ DPFPRINTF(("fragcache[%d]: dropping overall fragment\n",
+ h->ip_id));
+- frag->fr_flags |= PFFRAG_DROP;
++ (*frag)->fr_flags |= PFFRAG_DROP;
+ }
+
+ m_freem(m);
+@@ -1085,12 +1089,12 @@
+
+ /* Might return a completely reassembled mbuf, or NULL */
+ DPFPRINTF(("reass frag %d @ %d-%d\n", h->ip_id, fragoff, max));
+- *m0 = m = pf_reassemble(m0, frag, frent, mff);
++ *m0 = m = pf_reassemble(m0, &frag, frent, mff);
+
+ if (m == NULL)
+ return (PF_DROP);
+
+- if (frag && (frag->fr_flags & PFFRAG_DROP))
++ if (frag != NULL && (frag->fr_flags & PFFRAG_DROP))
+ goto drop;
+
+ h = mtod(m, struct ip *);
+@@ -1119,7 +1123,7 @@
+ goto bad;
+ }
+
+- *m0 = m = pf_fragcache(m0, h, frag, mff,
++ *m0 = m = pf_fragcache(m0, h, &frag, mff,
+ (r->rule_flag & PFRULE_FRAGDROP) ? 1 : 0, &nomem);
+ if (m == NULL) {
+ if (nomem)
+@@ -1135,7 +1139,7 @@
+ goto no_mem;
+ m_tag_prepend(m, mtag);
+ }
+- if (frag && (frag->fr_flags & PFFRAG_DROP))
++ if (frag != NULL && (frag->fr_flags & PFFRAG_DROP))
+ goto drop;
+ goto fragment_pass;
+ }
OpenPOWER on IntegriCloud