Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src - nbuf_ensure_contig: rework to use m_ensure_contig(9), whic...



details:   https://anonhg.NetBSD.org/src/rev/a8597f79881d
branches:  trunk
changeset: 784169:a8597f79881d
user:      rmind <rmind%NetBSD.org@localhost>
date:      Sun Jan 20 18:45:56 2013 +0000

description:
- nbuf_ensure_contig: rework to use m_ensure_contig(9), which will not free
  the mbuf chain on failure.  Fixes some corner cases.  Improve regression
  test and sprinkle some asserts.
- npf_reassembly: clear nbuf on IPv6 reassembly failure path (partial fix).
  The problem was found and fix provided by Anthony Mallet.

diffstat:

 sys/net/npf/npf_handler.c                       |   9 ++-
 sys/net/npf/npf_mbuf.c                          |  66 +++++++++++++-----------
 sys/net/npf/npf_processor.c                     |  11 ++-
 sys/net/npf/npf_rproc.c                         |   7 ++-
 sys/net/npf/npf_ruleset.c                       |   7 +-
 sys/net/npf/npf_session.c                       |   9 ++-
 usr.sbin/npf/npftest/libnpftest/npf_nbuf_test.c |  23 +++++++-
 7 files changed, 87 insertions(+), 45 deletions(-)

diffs (truncated from 338 to 300 lines):

diff -r 80a9a1bee96e -r a8597f79881d sys/net/npf/npf_handler.c
--- a/sys/net/npf/npf_handler.c Sun Jan 20 18:45:19 2013 +0000
+++ b/sys/net/npf/npf_handler.c Sun Jan 20 18:45:56 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: npf_handler.c,v 1.24 2012/12/24 19:05:43 rmind Exp $   */
+/*     $NetBSD: npf_handler.c,v 1.25 2013/01/20 18:45:56 rmind Exp $   */
 
 /*-
  * Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_handler.c,v 1.24 2012/12/24 19:05:43 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_handler.c,v 1.25 2013/01/20 18:45:56 rmind Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -91,6 +91,9 @@
                 */
                const u_int hlen = npf_cache_hlen(npc);
                error = ip6_reass_packet(mp, hlen);
+               if (error && *mp == NULL) {
+                       memset(nbuf, 0, sizeof(nbuf_t));
+               }
 #endif
        }
        if (error) {
@@ -249,7 +252,7 @@
 
        /* Reset mbuf pointer before returning to the caller. */
        if ((*mp = nbuf_head_mbuf(&nbuf)) == NULL) {
-               return ENOMEM;
+               return error ? error : ENOMEM;
        }
 
        /* Pass the packet if decided and there is no error. */
diff -r 80a9a1bee96e -r a8597f79881d sys/net/npf/npf_mbuf.c
--- a/sys/net/npf/npf_mbuf.c    Sun Jan 20 18:45:19 2013 +0000
+++ b/sys/net/npf/npf_mbuf.c    Sun Jan 20 18:45:56 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: npf_mbuf.c,v 1.9 2012/12/24 19:05:44 rmind Exp $       */
+/*     $NetBSD: npf_mbuf.c,v 1.10 2013/01/20 18:45:56 rmind Exp $      */
 
 /*-
  * Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_mbuf.c,v 1.9 2012/12/24 19:05:44 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_mbuf.c,v 1.10 2013/01/20 18:45:56 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/mbuf.h>
@@ -160,47 +160,53 @@
 void *
 nbuf_ensure_contig(nbuf_t *nbuf, size_t len)
 {
-       struct mbuf *m = nbuf->nb_mbuf;
-       const u_int off = (uintptr_t)nbuf->nb_nptr - mtod(m, uintptr_t);
-       int tlen = off + len;
+       const struct mbuf * const n = nbuf->nb_mbuf;
+       const size_t off = (uintptr_t)nbuf->nb_nptr - mtod(n, uintptr_t);
+
+       KASSERT(off < n->m_len);
 
-       KASSERT(off < m_length(nbuf->nb_mbuf0));
-
-       if (__predict_false(m->m_len < tlen)) {
-               const bool head_buf = (nbuf->nb_mbuf0 == m);
-               const int target = NBUF_ENSURE_ROUNDUP(tlen);
-               const int pleft = m_length(m);
+       if (__predict_false(n->m_len < (off + len))) {
+               struct mbuf *m = nbuf->nb_mbuf0;
+               const size_t foff = nbuf_offset(nbuf);
+               const size_t plen = m_length(m);
+               const size_t mlen = m->m_len;
+               size_t target;
+               bool success;
 
                npf_stats_inc(NPF_STAT_NBUF_NONCONTIG);
 
                /* Attempt to round-up to NBUF_ENSURE_ALIGN bytes. */
-               if (target <= pleft) {
-                       tlen = target;
+               if ((target = NBUF_ENSURE_ROUNDUP(foff + len)) > plen) {
+                       target = foff + len;
                }
 
                /* Rearrange the chain to be contiguous. */
-               if ((m = m_pullup(m, tlen)) == NULL) {
-                       npf_stats_inc(NPF_STAT_NBUF_CONTIG_FAIL);
-                       memset(nbuf, 0, sizeof(nbuf_t));
-                       return NULL;
+               KASSERT((m->m_flags & M_PKTHDR) != 0);
+               success = m_ensure_contig(&m, target);
+               KASSERT(m != NULL);
+
+               /* If no change in the chain: return what we have. */
+               if (m == nbuf->nb_mbuf0 && m->m_len == mlen) {
+                       return success ? nbuf->nb_nptr : NULL;
                }
 
                /*
-                * If the buffer was re-allocated, indicate that references
-                * to the data would need reset.  Also, it was the head
-                * buffer - update our record.
+                * The mbuf chain was re-arranged.  Update the pointers
+                * accordingly and indicate that the references to the data
+                * might need a reset.
                 */
-               if (nbuf->nb_mbuf != m) {
-                       nbuf->nb_flags |= NBUF_DATAREF_RESET;
+               KASSERT((m->m_flags & M_PKTHDR) != 0);
+               nbuf->nb_mbuf0 = m;
+               nbuf->nb_mbuf = m;
+
+               KASSERT(foff < m->m_len && foff < m_length(m));
+               nbuf->nb_nptr = mtod(m, uint8_t *) + foff;
+               nbuf->nb_flags |= NBUF_DATAREF_RESET;
+
+               if (!success) {
+                       npf_stats_inc(NPF_STAT_NBUF_CONTIG_FAIL);
+                       return NULL;
                }
-               if (head_buf) {
-                       KASSERT((m->m_flags & M_PKTHDR) != 0);
-                       KASSERT(off < m_length(m));
-                       nbuf->nb_mbuf0 = m;
-               }
-
-               nbuf->nb_mbuf = m;
-               nbuf->nb_nptr = mtod(m, uint8_t *) + off;
        }
        return nbuf->nb_nptr;
 }
diff -r 80a9a1bee96e -r a8597f79881d sys/net/npf/npf_processor.c
--- a/sys/net/npf/npf_processor.c       Sun Jan 20 18:45:19 2013 +0000
+++ b/sys/net/npf/npf_processor.c       Sun Jan 20 18:45:56 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: npf_processor.c,v 1.13 2012/12/24 19:05:44 rmind Exp $ */
+/*     $NetBSD: npf_processor.c,v 1.14 2013/01/20 18:45:56 rmind Exp $ */
 
 /*-
  * Copyright (c) 2009-2010 The NetBSD Foundation, Inc.
@@ -50,7 +50,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_processor.c,v 1.13 2012/12/24 19:05:44 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_processor.c,v 1.14 2013/01/20 18:45:56 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -182,12 +182,13 @@
                KASSERT(i < NPF_NREGS);
                KASSERT(n >= sizeof(uint8_t) && n <= sizeof(uint32_t));
 
-               if ((n_ptr = nbuf_ensure_contig(nbuf, n)) == NULL) {
-                       goto fail;
-               }
+               n_ptr = nbuf_ensure_contig(nbuf, n);
                if (nbuf_flag_p(nbuf, NBUF_DATAREF_RESET)) {
                        npf_recache(npc, nbuf);
                }
+               if (n_ptr == NULL) {
+                       goto fail;
+               }
                memcpy(&regs[i], n_ptr, n);
                break;
        }
diff -r 80a9a1bee96e -r a8597f79881d sys/net/npf/npf_rproc.c
--- a/sys/net/npf/npf_rproc.c   Sun Jan 20 18:45:19 2013 +0000
+++ b/sys/net/npf/npf_rproc.c   Sun Jan 20 18:45:56 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: npf_rproc.c,v 1.4 2012/10/03 12:24:56 mlelstv Exp $    */
+/*     $NetBSD: npf_rproc.c,v 1.5 2013/01/20 18:45:56 rmind Exp $      */
 
 /*-
  * Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
@@ -263,6 +263,7 @@
 {
        const unsigned extcount = rp->rp_ext_count;
 
+       KASSERT(!nbuf_flag_p(nbuf, NBUF_DATAREF_RESET));
        KASSERT(rp->rp_refcnt > 0);
 
        for (unsigned i = 0; i < extcount; i++) {
@@ -271,5 +272,9 @@
 
                KASSERT(ext->ext_refcnt > 0);
                extops->proc(npc, nbuf, rp->rp_ext_meta[i], decision);
+
+               if (nbuf_flag_p(nbuf, NBUF_DATAREF_RESET)) {
+                       npf_recache(npc, nbuf);
+               }
        }
 }
diff -r 80a9a1bee96e -r a8597f79881d sys/net/npf/npf_ruleset.c
--- a/sys/net/npf/npf_ruleset.c Sun Jan 20 18:45:19 2013 +0000
+++ b/sys/net/npf/npf_ruleset.c Sun Jan 20 18:45:56 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: npf_ruleset.c,v 1.15 2012/12/24 19:05:44 rmind Exp $   */
+/*     $NetBSD: npf_ruleset.c,v 1.16 2013/01/20 18:45:56 rmind Exp $   */
 
 /*-
  * Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_ruleset.c,v 1.15 2012/12/24 19:05:44 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_ruleset.c,v 1.16 2013/01/20 18:45:56 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -367,6 +367,7 @@
        KASSERT(((di & PFIL_IN) != 0) ^ ((di & PFIL_OUT) != 0));
 again:
        TAILQ_FOREACH(rl, &rlset->rs_queue, r_entry) {
+               KASSERT(!nbuf_flag_p(nbuf, NBUF_DATAREF_RESET));
                KASSERT(!final_rl || rl->r_priority >= final_rl->r_priority);
 
                /* Match the interface. */
@@ -401,6 +402,8 @@
                final_rl = NULL;
                goto again;
        }
+
+       KASSERT(!nbuf_flag_p(nbuf, NBUF_DATAREF_RESET));
        return final_rl;
 }
 
diff -r 80a9a1bee96e -r a8597f79881d sys/net/npf/npf_session.c
--- a/sys/net/npf/npf_session.c Sun Jan 20 18:45:19 2013 +0000
+++ b/sys/net/npf/npf_session.c Sun Jan 20 18:45:56 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: npf_session.c,v 1.19 2012/12/24 19:05:45 rmind Exp $   */
+/*     $NetBSD: npf_session.c,v 1.20 2013/01/20 18:45:56 rmind Exp $   */
 
 /*-
  * Copyright (c) 2010-2012 The NetBSD Foundation, Inc.
@@ -80,7 +80,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_session.c,v 1.19 2012/12/24 19:05:45 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_session.c,v 1.20 2013/01/20 18:45:56 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -570,6 +570,8 @@
        npf_session_t *se;
        bool forw;
 
+       KASSERT(!nbuf_flag_p(nbuf, NBUF_DATAREF_RESET));
+
        /*
         * Check if session tracking is on.  Also, if layer 3 and 4 are not
         * cached - protocol is not supported or packet is invalid.
@@ -590,6 +592,7 @@
                *error = ENOMEM;
                return NULL;
        }
+       KASSERT(!nbuf_flag_p(nbuf, NBUF_DATAREF_RESET));
 
        /* Main lookup of the session. */
        if ((se = npf_session_lookup(npc, nbuf, di, &forw)) == NULL) {
@@ -625,6 +628,8 @@
        u_int proto, alen;
        bool ok;
 
+       KASSERT(!nbuf_flag_p(nbuf, NBUF_DATAREF_RESET));
+
        /*
         * Check if session tracking is on.  Also, if layer 3 and 4 are not
         * cached - protocol is not supported or packet is invalid.
diff -r 80a9a1bee96e -r a8597f79881d usr.sbin/npf/npftest/libnpftest/npf_nbuf_test.c
--- a/usr.sbin/npf/npftest/libnpftest/npf_nbuf_test.c   Sun Jan 20 18:45:19 2013 +0000
+++ b/usr.sbin/npf/npftest/libnpftest/npf_nbuf_test.c   Sun Jan 20 18:45:56 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: npf_nbuf_test.c,v 1.3 2012/12/24 19:05:48 rmind Exp $  */
+/*     $NetBSD: npf_nbuf_test.c,v 1.4 2013/01/20 18:45:57 rmind Exp $  */
 
 /*
  * NPF nbuf interface test.
@@ -16,23 +16,41 @@
 
 CTASSERT((MBUF_CHAIN_LEN % sizeof(uint32_t)) == 0);
 
+static void
+mbuf_consistency_check(nbuf_t *nbuf)
+{
+       struct mbuf *m = nbuf_head_mbuf(nbuf);
+
+       while (m) {
+               assert(m->m_type != MT_FREE);
+               m = m->m_next;
+       }



Home | Main Index | Thread Index | Old Index