Module Name:    src
Committed By:   ozaki-r
Date:           Thu May 25 03:36:36 UTC 2017

Modified Files:
        src/sys/netipsec: key.c

Log Message:
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.


To generate a diff of this commit:
cvs rdiff -u -r1.140 -r1.141 src/sys/netipsec/key.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/netipsec/key.c
diff -u src/sys/netipsec/key.c:1.140 src/sys/netipsec/key.c:1.141
--- src/sys/netipsec/key.c:1.140	Tue May 23 09:08:45 2017
+++ src/sys/netipsec/key.c	Thu May 25 03:36:36 2017
@@ -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(_acqtree, secacq) acqtr
 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 @@ key_timehandler_work(struct work *wk, vo
     {
 	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 @@ key_getspi(struct socket *so, struct mbu
 	/* 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 @@ key_acquire(const struct secasindex *sai
 	 * 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 @@ key_acquire(const struct secasindex *sai
 		/* 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 @@ key_getacq(const struct secasindex *said
 {
 	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 @@ key_getacqbyseq(u_int32_t seq)
 {
 	struct secacq *acq;
 
+	KASSERT(mutex_owned(&key_mtx));
+
 	LIST_FOREACH(acq, &acqtree, chain) {
 		if (acq->seq == seq)
 			return acq;
@@ -6511,8 +6525,10 @@ key_acquire2(struct socket *so, struct m
 			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 @@ key_acquire2(struct socket *so, struct m
 		/* 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 @@ key_register(struct socket *so, struct m
 	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 @@ key_freereg(struct socket *so)
 	 * 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 @@ key_do_init(void)
 {
 	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);

Reply via email to