The problem was reported around Aug 28. -current was fixed Aug 29 with
pf_norm.c 1.75, which is included in 3.4-release.

Backported patches against 3.3-stable and 3.2-stable were sent out
shortly after, but required testing. They were commited to their
respective branches Sep 24.

I'm not allowed to commit to -stable, I don't know the precise rules of
what gets listed on errata.html or even sent to security-announce. I
supply the patches and, when I'm told they require an errata entry, a
description. When, after that, things don't get commited, I send out a
reminder or two, but I'm not managing processes.

So, here's the description:

  Three cases of potential access to freed memory have been found in
  pf. At least one of them could be used to panic pf with active
  scrub rules remotely.

The patches are attached.

Daniel
Index: pf_norm.c
===================================================================
RCS file: /cvs/src/sys/net/pf_norm.c,v
retrieving revision 1.55
diff -u -r1.55 pf_norm.c
--- pf_norm.c   18 Feb 2003 08:05:15 -0000      1.55
+++ pf_norm.c   29 Aug 2003 09:36:55 -0000
@@ -105,10 +105,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 *);
@@ -308,7 +308,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;
@@ -319,33 +319,33 @@
        u_int16_t        off = ip->ip_off;
        u_int16_t        max = ip->ip_len + off;
 
-       KASSERT(frag == NULL || BUFFER_FRAGMENTS(frag));
+       KASSERT(*frag == NULL || BUFFER_FRAGMENTS(*frag));
 
        /* Strip off ip header */
        m->m_data += hlen;
        m->m_len -= hlen;
 
        /* Create a new reassembly queue for this packet */
-       if (frag == NULL) {
-               frag = pool_get(&pf_frag_pl, PR_NOWAIT);
-               if (frag == NULL) {
+       if (*frag == NULL) {
+               *frag = pool_get(&pf_frag_pl, PR_NOWAIT);
+               if (*frag == NULL) {
                        pf_flush_fragments();
-                       frag = pool_get(&pf_frag_pl, PR_NOWAIT);
-                       if (frag == NULL)
+                       *frag = pool_get(&pf_frag_pl, PR_NOWAIT);
+                       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_timeout = time.tv_sec;
-               LIST_INIT(&frag->fr_queue);
+               (*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_timeout = time.tv_sec;
+               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;
@@ -356,7 +356,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;
@@ -400,45 +400,46 @@
 
  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);
        KASSERT(frent != NULL);
        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);
@@ -460,11 +461,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;
@@ -492,7 +494,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;
@@ -502,41 +504,42 @@
        u_int16_t                max = ip_len + off;
        int                      hosed = 0;
 
-       KASSERT(frag == NULL || !BUFFER_FRAGMENTS(frag));
+       KASSERT(*frag == NULL || !BUFFER_FRAGMENTS(*frag));
 
        /* Create a new range queue for this packet */
-       if (frag == NULL) {
-               frag = pool_get(&pf_cache_pl, PR_NOWAIT);
-               if (frag == NULL) {
+       if (*frag == NULL) {
+               *frag = pool_get(&pf_cache_pl, PR_NOWAIT);
+               if (*frag == NULL) {
                        pf_flush_fragments();
-                       frag = pool_get(&pf_cache_pl, PR_NOWAIT);
-                       if (frag == NULL)
+                       *frag = pool_get(&pf_cache_pl, PR_NOWAIT);
+                       if (*frag == NULL)
                                goto no_mem;
                }
 
                /* Get an entry for the queue */
                cur = pool_get(&pf_cent_pl, PR_NOWAIT);
                if (cur == NULL) {
-                       pool_put(&pf_cache_pl, frag);
+                       pool_put(&pf_cache_pl, *frag);
+                       *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_timeout = time.tv_sec;
+               (*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_timeout = time.tv_sec;
 
                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));
 
@@ -548,7 +551,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;
@@ -735,21 +738,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);
@@ -758,8 +762,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);
@@ -767,15 +771,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);
@@ -887,12 +891,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 *);
@@ -921,7 +925,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)
@@ -937,7 +941,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;
        }

Index: pf_norm.c
===================================================================
RCS file: /cvs/src/sys/net/pf_norm.c,v
retrieving revision 1.35
diff -u -r1.35 pf_norm.c
--- pf_norm.c   28 Jun 2002 00:08:23 -0000      1.35
+++ pf_norm.c   29 Aug 2003 02:35:46 -0000
@@ -105,10 +105,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 *);
@@ -324,7 +324,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;
@@ -335,33 +335,33 @@
        u_int16_t off = ip->ip_off;
        u_int16_t max = ip->ip_len + off;
 
-       KASSERT(frag == NULL || BUFFER_FRAGMENTS(frag));
+       KASSERT(*frag == NULL || BUFFER_FRAGMENTS(*frag));
 
        /* Strip off ip header */
        m->m_data += hlen;
        m->m_len -= hlen;
 
        /* Create a new reassembly queue for this packet */
-       if (frag == NULL) {
-               frag = pool_get(&pf_frag_pl, PR_NOWAIT);
-               if (frag == NULL) {
+       if (*frag == NULL) {
+               *frag = pool_get(&pf_frag_pl, PR_NOWAIT);
+               if (*frag == NULL) {
                        pf_flush_fragments();
-                       frag = pool_get(&pf_frag_pl, PR_NOWAIT);
-                       if (frag == NULL)
+                       *frag = pool_get(&pf_frag_pl, PR_NOWAIT);
+                       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_timeout = time.tv_sec;
-               LIST_INIT(&frag->fr_queue);
+               (*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_timeout = time.tv_sec;
+               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;
@@ -372,7 +372,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;
@@ -419,45 +419,46 @@
 
  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);
        KASSERT(frent != NULL);
        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);
@@ -479,11 +480,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;
@@ -511,7 +513,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;
@@ -521,41 +523,41 @@
        u_int16_t max = ip_len + off;
        int hosed = 0;
 
-       KASSERT(frag == NULL || !BUFFER_FRAGMENTS(frag));
+       KASSERT(*frag == NULL || !BUFFER_FRAGMENTS(*frag));
 
        /* Create a new range queue for this packet */
-       if (frag == NULL) {
-               frag = pool_get(&pf_cache_pl, PR_NOWAIT);
-               if (frag == NULL) {
+       if (*frag == NULL) {
+               *frag = pool_get(&pf_cache_pl, PR_NOWAIT);
+               if (*frag == NULL) {
                        pf_flush_fragments();
-                       frag = pool_get(&pf_cache_pl, PR_NOWAIT);
-                       if (frag == NULL)
+                       *frag = pool_get(&pf_cache_pl, PR_NOWAIT);
+                       if (*frag == NULL)
                                goto no_mem;
                }
 
                /* Get an entry for the queue */
                cur = pool_get(&pf_cent_pl, PR_NOWAIT);
                if (cur == NULL) {
-                       pool_put(&pf_cache_pl, frag);
+                       pool_put(&pf_cache_pl, *frag);
                        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_timeout = time.tv_sec;
+               (*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_timeout = time.tv_sec;
 
                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));
 
@@ -567,7 +569,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;
@@ -752,21 +754,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);
@@ -775,8 +778,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);
@@ -784,15 +787,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);
@@ -897,12 +900,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 *);
@@ -931,7 +934,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)
@@ -946,7 +949,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;
        }

Attachment: pgp00000.pgp
Description: PGP signature

Reply via email to