Module Name:    src
Committed By:   ozaki-r
Date:           Mon Jul 10 07:45:10 UTC 2017

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

Log Message:
Make sure a sav is inserted to a sah list after its initialization completes


To generate a diff of this commit:
cvs rdiff -u -r1.170 -r1.171 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.170 src/sys/netipsec/key.c:1.171
--- src/sys/netipsec/key.c:1.170	Mon Jul 10 07:40:23 2017
+++ src/sys/netipsec/key.c	Mon Jul 10 07:45:10 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: key.c,v 1.170 2017/07/10 07:40:23 ozaki-r Exp $	*/
+/*	$NetBSD: key.c,v 1.171 2017/07/10 07:45:10 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.170 2017/07/10 07:40:23 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.171 2017/07/10 07:45:10 ozaki-r Exp $");
 
 /*
  * This code is referd to RFC 2367
@@ -421,11 +421,10 @@ static u_int key_getspreqmsglen (const s
 static int key_spdexpire (struct secpolicy *);
 static struct secashead *key_newsah (const struct secasindex *);
 static void key_delsah (struct secashead *);
-static struct secasvar *key_newsav (struct mbuf *,
-	const struct sadb_msghdr *, struct secashead *, int *,
-	const char*, int);
-#define	KEY_NEWSAV(m, sadb, sah, e)				\
-	key_newsav(m, sadb, sah, e, __func__, __LINE__)
+static struct secasvar *key_newsav(struct mbuf *,
+	const struct sadb_msghdr *, int *, const char*, int);
+#define	KEY_NEWSAV(m, sadb, e)				\
+	key_newsav(m, sadb, e, __func__, __LINE__)
 static void key_delsav (struct secasvar *);
 static struct secashead *key_getsah(const struct secasindex *, int);
 static struct secasvar *key_checkspidup (const struct secasindex *, u_int32_t);
@@ -433,7 +432,7 @@ static struct secasvar *key_getsavbyspi 
 static int key_setsaval (struct secasvar *, struct mbuf *,
 	const struct sadb_msghdr *);
 static void key_freesaval(struct secasvar *);
-static int key_mature (struct secasvar *);
+static int key_init_xform(struct secasvar *);
 static void key_clear_xform(struct secasvar *);
 static struct mbuf *key_setdumpsa (struct secasvar *, u_int8_t,
 	u_int8_t, u_int32_t, u_int32_t);
@@ -1375,6 +1374,11 @@ key_freesav(struct secasvar **psav, cons
 
 	if (nv == 0) {
 		*psav = NULL;
+
+		/* remove from SA header */
+		KASSERT(__LIST_CHAINED(sav));
+		LIST_REMOVE(sav, chain);
+
 		key_delsav(sav);
 	}
 }
@@ -2903,8 +2907,7 @@ key_delsah(struct secashead *sah)
  */
 static struct secasvar *
 key_newsav(struct mbuf *m, const struct sadb_msghdr *mhp,
-	   struct secashead *sah, int *errp,
-	   const char* where, int tag)
+    int *errp, const char* where, int tag)
 {
 	struct secasvar *newsav;
 	const struct sadb_sa *xsa;
@@ -2913,7 +2916,6 @@ key_newsav(struct mbuf *m, const struct 
 	KASSERT(m != NULL);
 	KASSERT(mhp != NULL);
 	KASSERT(mhp->msg != NULL);
-	KASSERT(sah != NULL);
 
 	newsav = kmem_zalloc(sizeof(struct secasvar), KM_SLEEP);
 
@@ -2958,12 +2960,6 @@ key_newsav(struct mbuf *m, const struct 
 	newsav->created = time_uptime;
 	newsav->pid = mhp->msg->sadb_msg_pid;
 
-	/* add to satree */
-	newsav->sah = sah;
-	newsav->refcnt = 1;
-	newsav->state = SADB_SASTATE_LARVAL;
-	LIST_INSERT_TAIL(&sah->savtree[SADB_SASTATE_LARVAL], newsav,
-	    secasvar, chain);
 	KEYDEBUG_PRINTF(KEYDEBUG_IPSEC_STAMP,
 	    "DP from %s:%u return SA:%p\n", where, tag, newsav);
 	return newsav;
@@ -3008,10 +3004,6 @@ key_delsav(struct secasvar *sav)
 	KASSERT(sav != NULL);
 	KASSERTMSG(sav->refcnt == 0, "reference count %u > 0", sav->refcnt);
 
-	/* remove from SA header */
-	KASSERT(__LIST_CHAINED(sav));
-	LIST_REMOVE(sav, chain);
-
 	key_clear_xform(sav);
 	key_freesaval(sav);
 	kmem_intr_free(sav, sizeof(*sav));
@@ -3348,10 +3340,13 @@ key_setsaval(struct secasvar *sav, struc
  *	other:	errno
  */
 static int
-key_mature(struct secasvar *sav)
+key_init_xform(struct secasvar *sav)
 {
 	int error;
 
+	/* We shouldn't initialize sav variables while someone uses it. */
+	KASSERT(sav->refcnt == 0);
+
 	/* check SPI value */
 	switch (sav->sah->saidx.proto) {
 	case IPPROTO_ESP:
@@ -3416,9 +3411,8 @@ key_mature(struct secasvar *sav)
 		error = EPROTONOSUPPORT;
 		break;
 	}
-	if (error == 0)
-		key_sa_chgstate(sav, SADB_SASTATE_MATURE);
-	return (error);
+
+	return error;
 }
 
 /*
@@ -4887,7 +4881,7 @@ key_api_getspi(struct socket *so, struct
 
 	/* get a new SA */
 	/* XXX rewrite */
-	newsav = KEY_NEWSAV(m, mhp, newsah, &error);
+	newsav = KEY_NEWSAV(m, mhp, &error);
 	if (newsav == NULL) {
 		/* XXX don't free new SA index allocated in above. */
 		return key_senderror(so, m, error);
@@ -4896,6 +4890,13 @@ key_api_getspi(struct socket *so, struct
 	/* set spi */
 	newsav->spi = htonl(spi);
 
+	/* add to satree */
+	newsav->refcnt = 1;
+	newsav->sah = newsah;
+	newsav->state = SADB_SASTATE_LARVAL;
+	LIST_INSERT_TAIL(&newsah->savtree[SADB_SASTATE_LARVAL], newsav,
+	    secasvar, chain);
+
 #ifndef IPSEC_NONBLOCK_ACQUIRE
 	/* delete the entry in acqtree */
 	if (mhp->msg->sadb_msg_seq != 0) {
@@ -5306,33 +5307,32 @@ key_api_update(struct socket *so, struct
 	newsav->seq = sav->seq;
 	newsav->created = sav->created;
 	newsav->pid = sav->pid;
+	newsav->sah = sav->sah;
 
 	error = key_setsaval(newsav, m, mhp);
 	if (error) {
-		KEY_FREESAV(&newsav);
+		key_delsav(newsav);
 		return key_senderror(so, m, error);
 	}
 
 	error = key_handle_natt_info(newsav, mhp);
 	if (error != 0) {
-		KEY_FREESAV(&newsav);
+		key_delsav(newsav);
 		return key_senderror(so, m, error);
 	}
 
-	/* add to satree */
-	newsav->sah = sah;
-	newsav->refcnt = 1;
-	newsav->state = sav->state;
-	/* We have to keep the order */
-	LIST_INSERT_AFTER(sav, newsav, chain);
-
-	/* check SA values to be mature. */
-	error = key_mature(newsav);
+	error = key_init_xform(newsav);
 	if (error != 0) {
-		KEY_FREESAV(&newsav);
+		key_delsav(newsav);
 		return key_senderror(so, m, error);
 	}
 
+	/* add to satree */
+	newsav->refcnt = 1;
+	newsav->state = SADB_SASTATE_MATURE;
+	LIST_INSERT_TAIL(&sah->savtree[SADB_SASTATE_MATURE], newsav,
+	    secasvar, chain);
+
 	key_sa_chgstate(sav, SADB_SASTATE_DEAD);
 	KEY_FREESAV(&sav);
 
@@ -5486,24 +5486,30 @@ key_api_add(struct socket *so, struct mb
 		IPSECLOG(LOG_DEBUG, "SA already exists.\n");
 		return key_senderror(so, m, EEXIST);
 	}
-	newsav = KEY_NEWSAV(m, mhp, newsah, &error);
+	newsav = KEY_NEWSAV(m, mhp, &error);
 	if (newsav == NULL) {
 		return key_senderror(so, m, error);
 	}
+	newsav->sah = newsah;
 
 	error = key_handle_natt_info(newsav, mhp);
 	if (error != 0) {
-		KEY_FREESAV(&newsav);
+		key_delsav(newsav);
 		return key_senderror(so, m, EINVAL);
 	}
 
-	/* check SA values to be mature. */
-	error = key_mature(newsav);
+	error = key_init_xform(newsav);
 	if (error != 0) {
-		KEY_FREESAV(&newsav);
+		key_delsav(newsav);
 		return key_senderror(so, m, error);
 	}
 
+	/* add to satree */
+	newsav->refcnt = 1;
+	newsav->state = SADB_SASTATE_MATURE;
+	LIST_INSERT_TAIL(&newsah->savtree[SADB_SASTATE_MATURE], newsav,
+	    secasvar, chain);
+
 	/*
 	 * don't call key_freesav() here, as we would like to keep the SA
 	 * in the database on success.

Reply via email to