Source-Changes-HG archive

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

[src/trunk]: src/sys/netipsec Protect acqtree and regtree with a mutex (key_mtx)



details:   https://anonhg.NetBSD.org/src/rev/b070ef95ef7b
branches:  trunk
changeset: 824129:b070ef95ef7b
user:      ozaki-r <ozaki-r%NetBSD.org@localhost>
date:      Thu May 25 03:36:36 2017 +0000

description:
Protect acqtree and regtree with a mutex (key_mtx)

The data structures aren't used in any performance-sensitive paths,
so just using a mutex to protect them is good enough.

diffstat:

 sys/netipsec/key.c |  53 +++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 39 insertions(+), 14 deletions(-)

diffs (183 lines):

diff -r 0d6cf176516e -r b070ef95ef7b sys/netipsec/key.c
--- a/sys/netipsec/key.c        Thu May 25 02:43:43 2017 +0000
+++ b/sys/netipsec/key.c        Thu May 25 03:36:36 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: key.c,v 1.140 2017/05/23 09:08:45 ozaki-r Exp $        */
+/*     $NetBSD: key.c,v 1.141 2017/05/25 03:36:36 ozaki-r Exp $        */
 /*     $FreeBSD: src/sys/netipsec/key.c,v 1.3.2.3 2004/02/14 22:23:23 bms Exp $        */
 /*     $KAME: key.c,v 1.191 2001/06/27 10:46:49 sakane Exp $   */
 
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.140 2017/05/23 09:08:45 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.141 2017/05/25 03:36:36 ozaki-r Exp $");
 
 /*
  * This code is referd to RFC 2367
@@ -154,6 +154,11 @@
 static LIST_HEAD(_spacqtree, secspacq) spacqtree;      /* SP acquiring list */
 #endif
 
+/*
+ * Protect regtree, acqtree and items stored in the lists.
+ */
+static kmutex_t key_mtx __cacheline_aligned;
+
 /* search order for SAs */
        /*
         * This order is important because we must select the oldest SA
@@ -4669,13 +4674,17 @@
     {
        struct secacq *acq, *nextacq;
 
+    restart:
+       mutex_enter(&key_mtx);
        LIST_FOREACH_SAFE(acq, &acqtree, chain, nextacq) {
                if (now - acq->created > key_blockacq_lifetime) {
-                       KASSERT(__LIST_CHAINED(acq));
                        LIST_REMOVE(acq, chain);
+                       mutex_exit(&key_mtx);
                        kmem_free(acq, sizeof(*acq));
-               }
-       }
+                       goto restart;
+               }
+       }
+       mutex_exit(&key_mtx);
     }
 #endif
 
@@ -4903,12 +4912,14 @@
        /* delete the entry in acqtree */
        if (mhp->msg->sadb_msg_seq != 0) {
                struct secacq *acq;
+               mutex_enter(&key_mtx);
                acq = key_getacqbyseq(mhp->msg->sadb_msg_seq);
                if (acq != NULL) {
                        /* reset counter in order to deletion by timehandler. */
                        acq->created = time_uptime;
                        acq->count = 0;
                }
+               mutex_exit(&key_mtx);
        }
 #endif
 
@@ -6226,6 +6237,7 @@
         * managed with ACQUIRING list.
         */
        /* Get an entry to check whether sending message or not. */
+       mutex_enter(&key_mtx);
        newacq = key_getacq(saidx);
        if (newacq != NULL) {
                if (key_blockacq_count < newacq->count) {
@@ -6245,11 +6257,9 @@
                /* add to acqtree */
                LIST_INSERT_HEAD(&acqtree, newacq, chain);
        }
-#endif
-
-
-#ifndef IPSEC_NONBLOCK_ACQUIRE
+
        seq = newacq->seq;
+       mutex_exit(&key_mtx);
 #else
        seq = (acq_seq = (acq_seq == ~0 ? 1 : ++acq_seq));
 #endif
@@ -6408,6 +6418,8 @@
 {
        struct secacq *acq;
 
+       KASSERT(mutex_owned(&key_mtx));
+
        LIST_FOREACH(acq, &acqtree, chain) {
                if (key_cmpsaidx(saidx, &acq->saidx, CMP_EXACTLY))
                        return acq;
@@ -6421,6 +6433,8 @@
 {
        struct secacq *acq;
 
+       KASSERT(mutex_owned(&key_mtx));
+
        LIST_FOREACH(acq, &acqtree, chain) {
                if (acq->seq == seq)
                        return acq;
@@ -6511,8 +6525,10 @@
                        return 0;
                }
 
+               mutex_enter(&key_mtx);
                acq = key_getacqbyseq(mhp->msg->sadb_msg_seq);
                if (acq == NULL) {
+                       mutex_exit(&key_mtx);
                        /*
                         * the specified larval SA is already gone, or we got
                         * a bogus sequence number.  we can silently ignore it.
@@ -6524,6 +6540,7 @@
                /* reset acq counter in order to deletion by timehander. */
                acq->created = time_uptime;
                acq->count = 0;
+               mutex_exit(&key_mtx);
 #endif
                m_freem(m);
                return 0;
@@ -6622,22 +6639,26 @@
        if (mhp->msg->sadb_msg_satype == SADB_SATYPE_UNSPEC)
                goto setmsg;
 
+       /* Allocate regnode in advance, out of mutex */
+       newreg = kmem_zalloc(sizeof(*newreg), KM_SLEEP);
+
        /* check whether existing or not */
+       mutex_enter(&key_mtx);
        LIST_FOREACH(reg, &regtree[mhp->msg->sadb_msg_satype], chain) {
                if (reg->so == so) {
                        IPSECLOG(LOG_DEBUG, "socket exists already.\n");
+                       mutex_exit(&key_mtx);
+                       kmem_free(newreg, sizeof(*newreg));
                        return key_senderror(so, m, EEXIST);
                }
        }
 
-       /* create regnode */
-       newreg = kmem_zalloc(sizeof(*newreg), KM_SLEEP);
-
        newreg->so = so;
        ((struct keycb *)sotorawcb(so))->kp_registered++;
 
        /* add regnode to regtree. */
        LIST_INSERT_HEAD(&regtree[mhp->msg->sadb_msg_satype], newreg, chain);
+       mutex_exit(&key_mtx);
 
   setmsg:
     {
@@ -6763,14 +6784,16 @@
         * one socket is registered to multiple type of SA.
         */
        for (i = 0; i <= SADB_SATYPE_MAX; i++) {
+               mutex_enter(&key_mtx);
                LIST_FOREACH(reg, &regtree[i], chain) {
                        if (reg->so == so) {
-                               KASSERT(__LIST_CHAINED(reg));
                                LIST_REMOVE(reg, chain);
-                               kmem_free(reg, sizeof(*reg));
                                break;
                        }
                }
+               mutex_exit(&key_mtx);
+               if (reg != NULL)
+                       kmem_free(reg, sizeof(*reg));
        }
 
        return;
@@ -7669,6 +7692,8 @@
 {
        int i, error;
 
+       mutex_init(&key_mtx, MUTEX_DEFAULT, IPL_NONE);
+
        pfkeystat_percpu = percpu_alloc(sizeof(uint64_t) * PFKEY_NSTATS);
 
        callout_init(&key_timehandler_ch, 0);



Home | Main Index | Thread Index | Old Index