Module Name:    src
Committed By:   martin
Date:           Thu Nov 14 15:32:32 UTC 2019

Modified Files:
        src/sys/netipsec [netbsd-9]: key.c

Log Message:
Pull up following revision(s) (requested by knakahara in ticket #423):

        sys/netipsec/key.c: revision 1.268
        sys/netipsec/key.c: revision 1.269

Fix SA can be expaired wrongly when there are many SPs.

When key_timehandler_spd() spent over one second, the "now" argument of
key_timehandler_sad() could be older than sav->created. That caused SA
was expired immediately.

 -

Reduce load for IKE negotiations when the system has many IPv6 addresses.
e.g. the system has many vlan(4), gif(4) or ipsecif(4) with link local address.


To generate a diff of this commit:
cvs rdiff -u -r1.265.2.1 -r1.265.2.2 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.265.2.1 src/sys/netipsec/key.c:1.265.2.2
--- src/sys/netipsec/key.c:1.265.2.1	Sun Sep  1 10:49:37 2019
+++ src/sys/netipsec/key.c	Thu Nov 14 15:32:32 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: key.c,v 1.265.2.1 2019/09/01 10:49:37 martin Exp $	*/
+/*	$NetBSD: key.c,v 1.265.2.2 2019/11/14 15:32:32 martin Exp $	*/
 /*	$FreeBSD: 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.265.2.1 2019/09/01 10:49:37 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.265.2.2 2019/11/14 15:32:32 martin Exp $");
 
 /*
  * This code is referred to RFC 2367
@@ -4495,30 +4495,34 @@ key_ismyaddr6(const struct sockaddr_in6 
 	bound = curlwp_bind();
 	s = pserialize_read_enter();
 	IN6_ADDRLIST_READER_FOREACH(ia) {
-		bool ingroup;
-
 		if (key_sockaddr_match((const struct sockaddr *)&sin6,
 		    (const struct sockaddr *)&ia->ia_addr, 0)) {
 			pserialize_read_exit(s);
 			goto ours;
 		}
-		ia6_acquire(ia, &psref);
-		pserialize_read_exit(s);
 
-		/*
-		 * XXX Multicast
-		 * XXX why do we care about multlicast here while we don't care
-		 * about IPv4 multicast??
-		 * XXX scope
-		 */
-		ingroup = in6_multi_group(&sin6->sin6_addr, ia->ia_ifp);
-		if (ingroup) {
+		if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
+			bool ingroup;
+
+			ia6_acquire(ia, &psref);
+			pserialize_read_exit(s);
+
+			/*
+			 * XXX Multicast
+			 * XXX why do we care about multlicast here while we don't care
+			 * about IPv4 multicast??
+			 * XXX scope
+			 */
+			ingroup = in6_multi_group(&sin6->sin6_addr, ia->ia_ifp);
+			if (ingroup) {
+				ia6_release(ia, &psref);
+				goto ours;
+			}
+
+			s = pserialize_read_enter();
 			ia6_release(ia, &psref);
-			goto ours;
 		}
 
-		s = pserialize_read_enter();
-		ia6_release(ia, &psref);
 	}
 	pserialize_read_exit(s);
 
@@ -4876,14 +4880,20 @@ key_bb_match_withmask(const void *a1, co
 }
 
 static void
-key_timehandler_spd(time_t now)
+key_timehandler_spd(void)
 {
 	u_int dir;
 	struct secpolicy *sp;
+	volatile time_t now;
 
 	for (dir = 0; dir < IPSEC_DIR_MAX; dir++) {
 	    retry:
 		mutex_enter(&key_spd.lock);
+		/*
+		 * To avoid for sp->created to overtake "now" because of
+		 * wating mutex, set time_uptime here.
+		 */
+		now = time_uptime;
 		SPLIST_WRITER_FOREACH(sp, dir) {
 			KASSERT(sp->state != IPSEC_SPSTATE_DEAD);
 
@@ -4917,10 +4927,11 @@ key_timehandler_spd(time_t now)
 }
 
 static void
-key_timehandler_sad(time_t now)
+key_timehandler_sad(void)
 {
 	struct secashead *sah;
 	int s;
+	volatile time_t now;
 
 restart:
 	mutex_enter(&key_sad.lock);
@@ -4946,6 +4957,10 @@ restart:
 		/* if LARVAL entry doesn't become MATURE, delete it. */
 		mutex_enter(&key_sad.lock);
 	restart_sav_LARVAL:
+		/*
+		 * Same as key_timehandler_spd(), set time_uptime here.
+		 */
+		now = time_uptime;
 		SAVLIST_WRITER_FOREACH(sav, sah, SADB_SASTATE_LARVAL) {
 			if (now - sav->created > key_larval_lifetime) {
 				key_sa_chgstate(sav, SADB_SASTATE_DEAD);
@@ -4960,6 +4975,10 @@ restart:
 		 */
 	restart_sav_MATURE:
 		mutex_enter(&key_sad.lock);
+		/*
+		 * ditto
+		 */
+		now = time_uptime;
 		SAVLIST_WRITER_FOREACH(sav, sah, SADB_SASTATE_MATURE) {
 			/* we don't need to check. */
 			if (sav->lft_s == NULL)
@@ -5024,6 +5043,10 @@ restart:
 		/* check DYING entry to change status to DEAD. */
 		mutex_enter(&key_sad.lock);
 	restart_sav_DYING:
+		/*
+		 * ditto
+		 */
+		now = time_uptime;
 		SAVLIST_WRITER_FOREACH(sav, sah, SADB_SASTATE_DYING) {
 			/* we don't need to check. */
 			if (sav->lft_h == NULL)
@@ -5090,13 +5113,18 @@ restart:
 }
 
 static void
-key_timehandler_acq(time_t now)
+key_timehandler_acq(void)
 {
 #ifndef IPSEC_NONBLOCK_ACQUIRE
 	struct secacq *acq, *nextacq;
+	volatile time_t now;
 
     restart:
 	mutex_enter(&key_misc.lock);
+	/*
+	 * Same as key_timehandler_spd(), set time_uptime here.
+	 */
+	now = time_uptime;
 	LIST_FOREACH_SAFE(acq, &key_misc.acqlist, chain, nextacq) {
 		if (now - acq->created > key_blockacq_lifetime) {
 			LIST_REMOVE(acq, chain);
@@ -5110,10 +5138,11 @@ key_timehandler_acq(time_t now)
 }
 
 static void
-key_timehandler_spacq(time_t now)
+key_timehandler_spacq(void)
 {
 #ifdef notyet
 	struct secspacq *acq, *nextacq;
+	time_t now = time_uptime;
 
 	LIST_FOREACH_SAFE(acq, &key_misc.spacqlist, chain, nextacq) {
 		if (now - acq->created > key_blockacq_lifetime) {
@@ -5135,15 +5164,14 @@ static unsigned int key_timehandler_work
 static void
 key_timehandler_work(struct work *wk, void *arg)
 {
-	time_t now = time_uptime;
 
 	/* We can allow enqueuing another work at this point */
 	atomic_swap_uint(&key_timehandler_work_enqueued, 0);
 
-	key_timehandler_spd(now);
-	key_timehandler_sad(now);
-	key_timehandler_acq(now);
-	key_timehandler_spacq(now);
+	key_timehandler_spd();
+	key_timehandler_sad();
+	key_timehandler_acq();
+	key_timehandler_spacq();
 
 	key_acquire_sendup_pending_mbuf();
 

Reply via email to