diff options
author | edwin <edwin@FreeBSD.org> | 2003-08-29 03:14:03 +0000 |
---|---|---|
committer | edwin <edwin@FreeBSD.org> | 2003-08-29 03:14:03 +0000 |
commit | 32bdf60426b15158f63d8fac3160221ebd1fe5eb (patch) | |
tree | 01634c3aed385d0bc17a4541ed57cf654158d9f4 | |
parent | 400a9a28e925e2b0e6193058d162dd6c117c6c3d (diff) | |
download | FreeBSD-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/Makefile | 2 | ||||
-rw-r--r-- | security/pf/files/patch-ag | 383 |
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; + } |