Module Name:    src
Committed By:   martin
Date:           Thu Nov 30 14:57:34 UTC 2017

Modified Files:
        src/sys/netipsec [netbsd-8]: ipsec.c key.c key.h

Log Message:
Pull up following revision(s) (requested by ozaki-r in ticket #406):
        sys/netipsec/key.c: revision 1.239
        sys/netipsec/key.c: revision 1.240
        sys/netipsec/key.c: revision 1.241
        sys/netipsec/key.c: revision 1.242
        sys/netipsec/key.h: revision 1.33
        sys/netipsec/ipsec.c: revision 1.123
        sys/netipsec/key.c: revision 1.236
        sys/netipsec/key.c: revision 1.237
        sys/netipsec/key.c: revision 1.238
Provide a function to call MGETHDR and MCLGET
The change fixes two usages of MGETHDR that don't check whether a mbuf is really
allocated before passing it to MCLGET.
Fix error handling of MCLGET in key_alloc_mbuf
Add missing splx to key_spdexpire
Use M_WAITOK to allocate mbufs wherever sleepable
Further changes will get rid of unnecessary NULL checks then.
Get rid of unnecessary NULL checks that are obsoleted by M_WAITOK
Simply the code by avoiding unnecessary error checks
- Remove unnecessary m_pullup for self-allocated mbufs
- Replace some if-fails-return sanity checks with KASSERT
Call key_sendup_mbuf immediately unless key_acquire is called in softint
We need to defer it only if it's called in softint to avoid deadlock.


To generate a diff of this commit:
cvs rdiff -u -r1.99.2.1 -r1.99.2.2 src/sys/netipsec/ipsec.c
cvs rdiff -u -r1.163.2.2 -r1.163.2.3 src/sys/netipsec/key.c
cvs rdiff -u -r1.19.2.1 -r1.19.2.2 src/sys/netipsec/key.h

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/ipsec.c
diff -u src/sys/netipsec/ipsec.c:1.99.2.1 src/sys/netipsec/ipsec.c:1.99.2.2
--- src/sys/netipsec/ipsec.c:1.99.2.1	Sat Oct 21 19:43:54 2017
+++ src/sys/netipsec/ipsec.c	Thu Nov 30 14:57:34 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: ipsec.c,v 1.99.2.1 2017/10/21 19:43:54 snj Exp $	*/
+/*	$NetBSD: ipsec.c,v 1.99.2.2 2017/11/30 14:57:34 martin Exp $	*/
 /*	$FreeBSD: /usr/local/www/cvsroot/FreeBSD/src/sys/netipsec/ipsec.c,v 1.2.2.2 2003/07/01 01:38:13 sam Exp $	*/
 /*	$KAME: ipsec.c,v 1.103 2001/05/24 07:14:18 sakane Exp $	*/
 
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ipsec.c,v 1.99.2.1 2017/10/21 19:43:54 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ipsec.c,v 1.99.2.2 2017/11/30 14:57:34 martin Exp $");
 
 /*
  * IPsec controller part.
@@ -1422,7 +1422,7 @@ ipsec_get_policy(struct secpolicy *polic
 	if (policy == NULL || mp == NULL)
 		return EINVAL;
 
-	*mp = key_sp2msg(policy);
+	*mp = key_sp2msg(policy, M_NOWAIT);
 	if (!*mp) {
 		IPSECLOG(LOG_DEBUG, "No more memory.\n");
 		return ENOBUFS;

Index: src/sys/netipsec/key.c
diff -u src/sys/netipsec/key.c:1.163.2.2 src/sys/netipsec/key.c:1.163.2.3
--- src/sys/netipsec/key.c:1.163.2.2	Tue Nov 21 11:11:20 2017
+++ src/sys/netipsec/key.c	Thu Nov 30 14:57:34 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: key.c,v 1.163.2.2 2017/11/21 11:11:20 martin Exp $	*/
+/*	$NetBSD: key.c,v 1.163.2.3 2017/11/30 14:57:34 martin 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.163.2.2 2017/11/21 11:11:20 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.163.2.3 2017/11/30 14:57:34 martin Exp $");
 
 /*
  * This code is referred to RFC 2367
@@ -601,23 +601,18 @@ key_msghdr_get_sockaddr(const struct sad
 	return PFKEY_ADDR_SADDR(mhp->ext[idx]);
 }
 
-static struct mbuf *
+static void
 key_fill_replymsg(struct mbuf *m, int seq)
 {
 	struct sadb_msg *msg;
 
-	if (m->m_len < sizeof(*msg)) {
-		m = m_pullup(m, sizeof(*msg));
-		if (m == NULL)
-			return NULL;
-	}
+	KASSERT(m->m_len >= sizeof(*msg));
+
 	msg = mtod(m, struct sadb_msg *);
 	msg->sadb_msg_errno = 0;
 	msg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len);
 	if (seq != 0)
 		msg->sadb_msg_seq = seq;
-
-	return m;
 }
 
 #if 0
@@ -684,17 +679,17 @@ static struct mbuf *key_setsadbxfrag (u_
 static void key_porttosaddr (union sockaddr_union *, u_int16_t);
 static int key_checksalen (const union sockaddr_union *);
 static struct mbuf *key_setsadbmsg (u_int8_t, u_int16_t, u_int8_t,
-	u_int32_t, pid_t, u_int16_t);
+	u_int32_t, pid_t, u_int16_t, int);
 static struct mbuf *key_setsadbsa (struct secasvar *);
-static struct mbuf *key_setsadbaddr (u_int16_t,
-	const struct sockaddr *, u_int8_t, u_int16_t);
+static struct mbuf *key_setsadbaddr(u_int16_t,
+	const struct sockaddr *, u_int8_t, u_int16_t, int);
 #if 0
 static struct mbuf *key_setsadbident (u_int16_t, u_int16_t, void *,
 	int, u_int64_t);
 #endif
 static struct mbuf *key_setsadbxsa2 (u_int8_t, u_int32_t, u_int16_t);
 static struct mbuf *key_setsadbxpolicy (u_int16_t, u_int8_t,
-	u_int32_t);
+	u_int32_t, int);
 static void *key_newbuf (const void *, u_int);
 #ifdef INET6
 static int key_ismyaddr6 (const struct sockaddr_in6 *);
@@ -748,12 +743,13 @@ static int key_api_get(struct socket *, 
 	const struct sadb_msghdr *);
 
 static void key_getcomb_setlifetime (struct sadb_comb *);
-static struct mbuf *key_getcomb_esp (void);
-static struct mbuf *key_getcomb_ah (void);
-static struct mbuf *key_getcomb_ipcomp (void);
-static struct mbuf *key_getprop (const struct secasindex *);
+static struct mbuf *key_getcomb_esp(int);
+static struct mbuf *key_getcomb_ah(int);
+static struct mbuf *key_getcomb_ipcomp(int);
+static struct mbuf *key_getprop(const struct secasindex *, int);
 
-static int key_acquire(const struct secasindex *, const struct secpolicy *);
+static int key_acquire(const struct secasindex *, const struct secpolicy *,
+	    int);
 static int key_acquire_sendup_mbuf_later(struct mbuf *);
 static void key_acquire_sendup_pending_mbuf(void);
 #ifndef IPSEC_NONBLOCK_ACQUIRE
@@ -787,7 +783,8 @@ static const char *key_getuserfqdn (void
 #endif
 static void key_sa_chgstate (struct secasvar *, u_int8_t);
 
-static struct mbuf *key_alloc_mbuf (int);
+static struct mbuf *key_alloc_mbuf(int, int);
+static struct mbuf *key_alloc_mbuf_simple(int, int);
 
 static void key_timehandler(void *);
 static void key_timehandler_work(struct work *, void *);
@@ -1025,7 +1022,7 @@ key_checkrequest(const struct ipsecreque
 	}
 
 	/* there is no SA */
-	error = key_acquire(saidx, isr->sp);
+	error = key_acquire(saidx, isr->sp, M_NOWAIT);
 	if (error != 0) {
 		/* XXX What should I do ? */
 		IPSECLOG(LOG_DEBUG, "error %d returned from key_acquire.\n",
@@ -1969,7 +1966,7 @@ key_newreqid(void)
  * copy secpolicy struct to sadb_x_policy structure indicated.
  */
 struct mbuf *
-key_sp2msg(const struct secpolicy *sp)
+key_sp2msg(const struct secpolicy *sp, int mflag)
 {
 	struct sadb_x_policy *xpl;
 	int tlen;
@@ -1980,7 +1977,7 @@ key_sp2msg(const struct secpolicy *sp)
 
 	tlen = key_getspreqmsglen(sp);
 
-	m = key_alloc_mbuf(tlen);
+	m = key_alloc_mbuf(tlen, mflag);
 	if (!m || m->m_next) {	/*XXX*/
 		if (m)
 			m_freem(m);
@@ -2029,7 +2026,11 @@ key_sp2msg(const struct secpolicy *sp)
 	return m;
 }
 
-/* m will not be freed nor modified */
+/*
+ * m will not be freed nor modified. It never return NULL.
+ * If it returns a mbuf of M_PKTHDR, the mbuf ensures to have
+ * contiguous length at least sizeof(struct sadb_msg).
+ */
 static struct mbuf *
 key_gather_mbuf(struct mbuf *m, const struct sadb_msghdr *mhp,
 		int ndeep, int nitem, ...)
@@ -2042,12 +2043,13 @@ key_gather_mbuf(struct mbuf *m, const st
 
 	KASSERT(m != NULL);
 	KASSERT(mhp != NULL);
+	KASSERT(!cpu_softintr_p());
 
 	va_start(ap, nitem);
 	for (i = 0; i < nitem; i++) {
 		idx = va_arg(ap, int);
-		if (idx < 0 || idx > SADB_EXT_MAX)
-			goto fail;
+		KASSERT(idx >= 0);
+		KASSERT(idx <= SADB_EXT_MAX);
 		/* don't attempt to pull empty extension */
 		if (idx == SADB_EXT_RESERVED && mhp->msg == NULL)
 			continue;
@@ -2058,29 +2060,22 @@ key_gather_mbuf(struct mbuf *m, const st
 		if (idx == SADB_EXT_RESERVED) {
 			CTASSERT(PFKEY_ALIGN8(sizeof(struct sadb_msg)) <= MHLEN);
 			len = PFKEY_ALIGN8(sizeof(struct sadb_msg));
-			MGETHDR(n, M_DONTWAIT, MT_DATA);
-			if (!n)
-				goto fail;
+			MGETHDR(n, M_WAITOK, MT_DATA);
 			n->m_len = len;
 			n->m_next = NULL;
 			m_copydata(m, 0, sizeof(struct sadb_msg),
 			    mtod(n, void *));
 		} else if (i < ndeep) {
 			len = mhp->extlen[idx];
-			n = key_alloc_mbuf(len);
-			if (!n || n->m_next) {	/*XXX*/
-				if (n)
-					m_freem(n);
-				goto fail;
-			}
+			n = key_alloc_mbuf(len, M_WAITOK);
+			KASSERT(n->m_next == NULL);
 			m_copydata(m, mhp->extoff[idx], mhp->extlen[idx],
 			    mtod(n, void *));
 		} else {
 			n = m_copym(m, mhp->extoff[idx], mhp->extlen[idx],
-			    M_DONTWAIT);
+			    M_WAITOK);
 		}
-		if (n == NULL)
-			goto fail;
+		KASSERT(n != NULL);
 
 		if (result)
 			m_cat(result, n);
@@ -2089,18 +2084,15 @@ key_gather_mbuf(struct mbuf *m, const st
 	}
 	va_end(ap);
 
-	if (result && (result->m_flags & M_PKTHDR) != 0) {
+	KASSERT(result != NULL);
+	if ((result->m_flags & M_PKTHDR) != 0) {
 		result->m_pkthdr.len = 0;
 		for (n = result; n; n = n->m_next)
 			result->m_pkthdr.len += n->m_len;
+		KASSERT(result->m_len >= sizeof(struct sadb_msg));
 	}
 
 	return result;
-
-fail:
-	va_end(ap);
-	m_freem(result);
-	return NULL;
 }
 
 /*
@@ -2278,13 +2270,8 @@ key_api_spdadd(struct socket *so, struct
 		    SADB_X_EXT_POLICY,
 		    SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST);
 	}
-	if (!n)
-		return key_senderror(so, m, ENOBUFS);
-
-	n = key_fill_replymsg(n, 0);
-	if (n == NULL)
-		return key_senderror(so, m, ENOBUFS);
 
+	key_fill_replymsg(n, 0);
 	off = 0;
 	mpolicy = m_pulldown(n, PFKEY_ALIGN8(sizeof(struct sadb_msg)),
 	    sizeof(*xpl), &off);
@@ -2404,18 +2391,30 @@ key_api_spddelete(struct socket *so, str
 	/* create new sadb_msg to reply. */
 	n = key_gather_mbuf(m, mhp, 1, 4, SADB_EXT_RESERVED,
 	    SADB_X_EXT_POLICY, SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST);
-	if (!n)
-		return key_senderror(so, m, ENOBUFS);
-
-	n = key_fill_replymsg(n, 0);
-	if (n == NULL)
-		return key_senderror(so, m, ENOBUFS);
-
+	key_fill_replymsg(n, 0);
 	m_freem(m);
 	return key_sendup_mbuf(so, n, KEY_SENDUP_ALL);
     }
 }
 
+static struct mbuf *
+key_alloc_mbuf_simple(int len, int mflag)
+{
+	struct mbuf *n;
+
+	KASSERT(mflag == M_NOWAIT || (mflag == M_WAITOK && !cpu_softintr_p()));
+
+	MGETHDR(n, mflag, MT_DATA);
+	if (n && len > MHLEN) {
+		MCLGET(n, mflag);
+		if ((n->m_flags & M_EXT) == 0) {
+			m_freem(n);
+			n = NULL;
+		}
+	}
+	return n;
+}
+
 /*
  * SADB_SPDDELETE2 processing
  * receive
@@ -2465,17 +2464,7 @@ key_api_spddelete2(struct socket *so, st
 	/* create new sadb_msg to reply. */
 	len = PFKEY_ALIGN8(sizeof(struct sadb_msg));
 
-	MGETHDR(n, M_DONTWAIT, MT_DATA);
-	if (n && len > MHLEN) {
-		MCLGET(n, M_DONTWAIT);
-		if ((n->m_flags & M_EXT) == 0) {
-			m_freem(n);
-			n = NULL;
-		}
-	}
-	if (!n)
-		return key_senderror(so, m, ENOBUFS);
-
+	n = key_alloc_mbuf_simple(len, M_WAITOK);
 	n->m_len = len;
 	n->m_next = NULL;
 	off = 0;
@@ -2486,20 +2475,13 @@ key_api_spddelete2(struct socket *so, st
 	KASSERTMSG(off == len, "length inconsistency");
 
 	n->m_next = m_copym(m, mhp->extoff[SADB_X_EXT_POLICY],
-	    mhp->extlen[SADB_X_EXT_POLICY], M_DONTWAIT);
-	if (!n->m_next) {
-		m_freem(n);
-		return key_senderror(so, m, ENOBUFS);
-	}
+	    mhp->extlen[SADB_X_EXT_POLICY], M_WAITOK);
 
 	n->m_pkthdr.len = 0;
 	for (nn = n; nn; nn = nn->m_next)
 		n->m_pkthdr.len += nn->m_len;
 
-	n = key_fill_replymsg(n, 0);
-	if (n == NULL)
-		return key_senderror(so, m, ENOBUFS);
-
+	key_fill_replymsg(n, 0);
 	m_freem(m);
 	return key_sendup_mbuf(so, n, KEY_SENDUP_ALL);
     }
@@ -2545,11 +2527,8 @@ key_api_spdget(struct socket *so, struct
 	n = key_setdumpsp(sp, SADB_X_SPDGET, mhp->msg->sadb_msg_seq,
 	    mhp->msg->sadb_msg_pid);
 	KEY_SP_UNREF(&sp); /* ref gained by key_getspbyid */
-	if (n != NULL) {
-		m_freem(m);
-		return key_sendup_mbuf(so, n, KEY_SENDUP_ONE);
-	} else
-		return key_senderror(so, m, ENOBUFS);
+	m_freem(m);
+	return key_sendup_mbuf(so, n, KEY_SENDUP_ONE);
 }
 
 #ifdef notyet
@@ -2718,13 +2697,6 @@ key_setspddump_chain(int *errorp, int *l
 			--cnt;
 			n = key_setdumpsp(sp, SADB_X_SPDDUMP, cnt, pid);
 
-			if (!n) {
-				*errorp = ENOBUFS;
-				if (m)
-					m_freem(m);
-				return (NULL);
-			}
-
 			totlen += n->m_pkthdr.len;
 			if (!m) {
 				m = n;
@@ -2871,42 +2843,33 @@ key_api_nat_map(struct socket *so, struc
 	return 0;
 }
 
+/*
+ * Never return NULL.
+ */
 static struct mbuf *
 key_setdumpsp(struct secpolicy *sp, u_int8_t type, u_int32_t seq, pid_t pid)
 {
 	struct mbuf *result = NULL, *m;
 
+	KASSERT(!cpu_softintr_p());
+
 	m = key_setsadbmsg(type, 0, SADB_SATYPE_UNSPEC, seq, pid,
-	    key_sp_refcnt(sp));
-	if (!m)
-		goto fail;
+	    key_sp_refcnt(sp), M_WAITOK);
 	result = m;
 
 	m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC,
-	    &sp->spidx.src.sa, sp->spidx.prefs, sp->spidx.ul_proto);
-	if (!m)
-		goto fail;
+	    &sp->spidx.src.sa, sp->spidx.prefs, sp->spidx.ul_proto, M_WAITOK);
 	m_cat(result, m);
 
 	m = key_setsadbaddr(SADB_EXT_ADDRESS_DST,
-	    &sp->spidx.dst.sa, sp->spidx.prefd, sp->spidx.ul_proto);
-	if (!m)
-		goto fail;
+	    &sp->spidx.dst.sa, sp->spidx.prefd, sp->spidx.ul_proto, M_WAITOK);
 	m_cat(result, m);
 
-	m = key_sp2msg(sp);
-	if (!m)
-		goto fail;
+	m = key_sp2msg(sp, M_WAITOK);
 	m_cat(result, m);
 
-	if ((result->m_flags & M_PKTHDR) == 0)
-		goto fail;
-
-	if (result->m_len < sizeof(struct sadb_msg)) {
-		result = m_pullup(result, sizeof(struct sadb_msg));
-		if (result == NULL)
-			goto fail;
-	}
+	KASSERT(result->m_flags & M_PKTHDR);
+	KASSERT(result->m_len >= sizeof(struct sadb_msg));
 
 	result->m_pkthdr.len = 0;
 	for (m = result; m; m = m->m_next)
@@ -2916,10 +2879,6 @@ key_setdumpsp(struct secpolicy *sp, u_in
 	    PFKEY_UNIT64(result->m_pkthdr.len);
 
 	return result;
-
-fail:
-	m_freem(result);
-	return NULL;
 }
 
 /*
@@ -2976,22 +2935,14 @@ key_spdexpire(struct secpolicy *sp)
 	KASSERT(sp != NULL);
 
 	/* set msg header */
-	m = key_setsadbmsg(SADB_X_SPDEXPIRE, 0, 0, 0, 0, 0);
-	if (!m) {
-		error = ENOBUFS;
-		goto fail;
-	}
+	m = key_setsadbmsg(SADB_X_SPDEXPIRE, 0, 0, 0, 0, 0, M_WAITOK);
 	result = m;
 
 	/* create lifetime extension (current and hard) */
 	len = PFKEY_ALIGN8(sizeof(*lt)) * 2;
-	m = key_alloc_mbuf(len);
-	if (!m || m->m_next) {	/*XXX*/
-		if (m)
-			m_freem(m);
-		error = ENOBUFS;
-		goto fail;
-	}
+	m = key_alloc_mbuf(len, M_WAITOK);
+	KASSERT(m->m_next == NULL);
+
 	memset(mtod(m, void *), 0, len);
 	lt = mtod(m, struct sadb_lifetime *);
 	lt->sadb_lifetime_len = PFKEY_UNIT64(sizeof(struct sadb_lifetime));
@@ -3011,42 +2962,20 @@ key_spdexpire(struct secpolicy *sp)
 
 	/* set sadb_address for source */
 	m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC, &sp->spidx.src.sa,
-	    sp->spidx.prefs, sp->spidx.ul_proto);
-	if (!m) {
-		error = ENOBUFS;
-		goto fail;
-	}
+	    sp->spidx.prefs, sp->spidx.ul_proto, M_WAITOK);
 	m_cat(result, m);
 
 	/* set sadb_address for destination */
 	m = key_setsadbaddr(SADB_EXT_ADDRESS_DST, &sp->spidx.dst.sa,
-	    sp->spidx.prefd, sp->spidx.ul_proto);
-	if (!m) {
-		error = ENOBUFS;
-		goto fail;
-	}
+	    sp->spidx.prefd, sp->spidx.ul_proto, M_WAITOK);
 	m_cat(result, m);
 
 	/* set secpolicy */
-	m = key_sp2msg(sp);
-	if (!m) {
-		error = ENOBUFS;
-		goto fail;
-	}
+	m = key_sp2msg(sp, M_WAITOK);
 	m_cat(result, m);
 
-	if ((result->m_flags & M_PKTHDR) == 0) {
-		error = EINVAL;
-		goto fail;
-	}
-
-	if (result->m_len < sizeof(struct sadb_msg)) {
-		result = m_pullup(result, sizeof(struct sadb_msg));
-		if (result == NULL) {
-			error = ENOBUFS;
-			goto fail;
-		}
-	}
+	KASSERT(result->m_flags & M_PKTHDR);
+	KASSERT(result->m_len >= sizeof(struct sadb_msg));
 
 	result->m_pkthdr.len = 0;
 	for (m = result; m; m = m->m_next)
@@ -3055,11 +2984,7 @@ key_spdexpire(struct secpolicy *sp)
 	mtod(result, struct sadb_msg *)->sadb_msg_len =
 	    PFKEY_UNIT64(result->m_pkthdr.len);
 
-	return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED);
-
- fail:
-	if (result)
-		m_freem(result);
+	error = key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED);
 	splx(s);
 	return error;
 }
@@ -3707,7 +3632,7 @@ key_init_xform(struct secasvar *sav)
 }
 
 /*
- * subroutine for SADB_GET and SADB_DUMP.
+ * subroutine for SADB_GET and SADB_DUMP. It never return NULL.
  */
 static struct mbuf *
 key_setdumpsa(struct secasvar *sav, u_int8_t type, u_int8_t satype,
@@ -3732,9 +3657,7 @@ key_setdumpsa(struct secasvar *sav, u_in
 
 	};
 
-	m = key_setsadbmsg(type, 0, satype, seq, pid, key_sa_refcnt(sav));
-	if (m == NULL)
-		goto fail;
+	m = key_setsadbmsg(type, 0, satype, seq, pid, key_sa_refcnt(sav), M_WAITOK);
 	result = m;
 
 	for (i = __arraycount(dumporder) - 1; i >= 0; i--) {
@@ -3754,13 +3677,13 @@ key_setdumpsa(struct secasvar *sav, u_in
 		case SADB_EXT_ADDRESS_SRC:
 			m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC,
 			    &sav->sah->saidx.src.sa,
-			    FULLMASK, IPSEC_ULPROTO_ANY);
+			    FULLMASK, IPSEC_ULPROTO_ANY, M_WAITOK);
 			break;
 
 		case SADB_EXT_ADDRESS_DST:
 			m = key_setsadbaddr(SADB_EXT_ADDRESS_DST,
 			    &sav->sah->saidx.dst.sa,
-			    FULLMASK, IPSEC_ULPROTO_ANY);
+			    FULLMASK, IPSEC_ULPROTO_ANY, M_WAITOK);
 			break;
 
 		case SADB_EXT_KEY_AUTH:
@@ -3843,19 +3766,14 @@ key_setdumpsa(struct secasvar *sav, u_in
 		}
 
 		KASSERT(!(m && p));
-		if (!m && !p)
-			goto fail;
+		KASSERT(m != NULL || p != NULL);
 		if (p && tres) {
-			M_PREPEND(tres, l, M_DONTWAIT);
-			if (!tres)
-				goto fail;
+			M_PREPEND(tres, l, M_WAITOK);
 			memcpy(mtod(tres, void *), p, l);
 			continue;
 		}
 		if (p) {
-			m = key_alloc_mbuf(l);
-			if (!m)
-				goto fail;
+			m = key_alloc_mbuf(l, M_WAITOK);
 			m_copyback(m, 0, l, p);
 		}
 
@@ -3867,11 +3785,7 @@ key_setdumpsa(struct secasvar *sav, u_in
 	m_cat(result, tres);
 	tres = NULL; /* avoid free on error below */
 
-	if (result->m_len < sizeof(struct sadb_msg)) {
-		result = m_pullup(result, sizeof(struct sadb_msg));
-		if (result == NULL)
-			goto fail;
-	}
+	KASSERT(result->m_len >= sizeof(struct sadb_msg));
 
 	result->m_pkthdr.len = 0;
 	for (m = result; m; m = m->m_next)
@@ -3881,11 +3795,6 @@ key_setdumpsa(struct secasvar *sav, u_in
 	    PFKEY_UNIT64(result->m_pkthdr.len);
 
 	return result;
-
-fail:
-	m_freem(result);
-	m_freem(tres);
-	return NULL;
 }
 
 
@@ -3901,12 +3810,8 @@ key_setsadbxtype(u_int16_t type)
 
 	len = PFKEY_ALIGN8(sizeof(struct sadb_x_nat_t_type));
 
-	m = key_alloc_mbuf(len);
-	if (!m || m->m_next) {	/*XXX*/
-		if (m)
-			m_freem(m);
-		return NULL;
-	}
+	m = key_alloc_mbuf(len, M_WAITOK);
+	KASSERT(m->m_next == NULL);
 
 	p = mtod(m, struct sadb_x_nat_t_type *);
 
@@ -3929,12 +3834,8 @@ key_setsadbxport(u_int16_t port, u_int16
 
 	len = PFKEY_ALIGN8(sizeof(struct sadb_x_nat_t_port));
 
-	m = key_alloc_mbuf(len);
-	if (!m || m->m_next) {	/*XXX*/
-		if (m)
-			m_freem(m);
-		return NULL;
-	}
+	m = key_alloc_mbuf(len, M_WAITOK);
+	KASSERT(m->m_next == NULL);
 
 	p = mtod(m, struct sadb_x_nat_t_port *);
 
@@ -3958,12 +3859,8 @@ key_setsadbxfrag(u_int16_t flen)
 
 	len = PFKEY_ALIGN8(sizeof(struct sadb_x_nat_t_frag));
 
-	m = key_alloc_mbuf(len);
-	if (!m || m->m_next) {  /*XXX*/
-		if (m)
-			m_freem(m);
-		return NULL;
-	}
+	m = key_alloc_mbuf(len, M_WAITOK);
+	KASSERT(m->m_next == NULL);
 
 	p = mtod(m, struct sadb_x_nat_t_frag *);
 
@@ -4062,7 +3959,7 @@ key_checksalen(const union sockaddr_unio
  */
 static struct mbuf *
 key_setsadbmsg(u_int8_t type,  u_int16_t tlen, u_int8_t satype,
-	       u_int32_t seq, pid_t pid, u_int16_t reserved)
+	       u_int32_t seq, pid_t pid, u_int16_t reserved, int mflag)
 {
 	struct mbuf *m;
 	struct sadb_msg *p;
@@ -4072,14 +3969,7 @@ key_setsadbmsg(u_int8_t type,  u_int16_t
 
 	len = PFKEY_ALIGN8(sizeof(struct sadb_msg));
 
-	MGETHDR(m, M_DONTWAIT, MT_DATA);
-	if (m && len > MHLEN) {
-		MCLGET(m, M_DONTWAIT);
-		if ((m->m_flags & M_EXT) == 0) {
-			m_freem(m);
-			m = NULL;
-		}
-	}
+	m = key_alloc_mbuf_simple(len, mflag);
 	if (!m)
 		return NULL;
 	m->m_pkthdr.len = m->m_len = len;
@@ -4111,12 +4001,8 @@ key_setsadbsa(struct secasvar *sav)
 	int len;
 
 	len = PFKEY_ALIGN8(sizeof(struct sadb_sa));
-	m = key_alloc_mbuf(len);
-	if (!m || m->m_next) {	/*XXX*/
-		if (m)
-			m_freem(m);
-		return NULL;
-	}
+	m = key_alloc_mbuf(len, M_WAITOK);
+	KASSERT(m->m_next == NULL);
 
 	p = mtod(m, struct sadb_sa *);
 
@@ -4138,7 +4024,7 @@ key_setsadbsa(struct secasvar *sav)
  */
 static struct mbuf *
 key_setsadbaddr(u_int16_t exttype, const struct sockaddr *saddr,
-		u_int8_t prefixlen, u_int16_t ul_proto)
+		u_int8_t prefixlen, u_int16_t ul_proto, int mflag)
 {
 	struct mbuf *m;
 	struct sadb_address *p;
@@ -4146,7 +4032,7 @@ key_setsadbaddr(u_int16_t exttype, const
 
 	len = PFKEY_ALIGN8(sizeof(struct sadb_address)) +
 	    PFKEY_ALIGN8(saddr->sa_len);
-	m = key_alloc_mbuf(len);
+	m = key_alloc_mbuf(len, mflag);
 	if (!m || m->m_next) {	/*XXX*/
 		if (m)
 			m_freem(m);
@@ -4227,12 +4113,8 @@ key_setsadbxsa2(u_int8_t mode, u_int32_t
 	size_t len;
 
 	len = PFKEY_ALIGN8(sizeof(struct sadb_x_sa2));
-	m = key_alloc_mbuf(len);
-	if (!m || m->m_next) {	/*XXX*/
-		if (m)
-			m_freem(m);
-		return NULL;
-	}
+	m = key_alloc_mbuf(len, M_WAITOK);
+	KASSERT(m->m_next == NULL);
 
 	p = mtod(m, struct sadb_x_sa2 *);
 
@@ -4252,14 +4134,15 @@ key_setsadbxsa2(u_int8_t mode, u_int32_t
  * set data into sadb_x_policy
  */
 static struct mbuf *
-key_setsadbxpolicy(const u_int16_t type, const u_int8_t dir, const u_int32_t id)
+key_setsadbxpolicy(const u_int16_t type, const u_int8_t dir, const u_int32_t id,
+    int mflag)
 {
 	struct mbuf *m;
 	struct sadb_x_policy *p;
 	size_t len;
 
 	len = PFKEY_ALIGN8(sizeof(struct sadb_x_policy));
-	m = key_alloc_mbuf(len);
+	m = key_alloc_mbuf(len, mflag);
 	if (!m || m->m_next) {	/*XXX*/
 		if (m)
 			m_freem(m);
@@ -5257,17 +5140,7 @@ key_api_getspi(struct socket *so, struct
 	len = PFKEY_ALIGN8(sizeof(struct sadb_msg)) +
 	    PFKEY_ALIGN8(sizeof(struct sadb_sa));
 
-	MGETHDR(n, M_DONTWAIT, MT_DATA);
-	if (len > MHLEN) {
-		MCLGET(n, M_DONTWAIT);
-		if ((n->m_flags & M_EXT) == 0) {
-			m_freem(n);
-			n = NULL;
-		}
-	}
-	if (!n)
-		return key_senderror(so, m, ENOBUFS);
-
+	n = key_alloc_mbuf_simple(len, M_WAITOK);
 	n->m_len = len;
 	n->m_next = NULL;
 	off = 0;
@@ -5285,23 +5158,14 @@ key_api_getspi(struct socket *so, struct
 
 	n->m_next = key_gather_mbuf(m, mhp, 0, 2, SADB_EXT_ADDRESS_SRC,
 	    SADB_EXT_ADDRESS_DST);
-	if (!n->m_next) {
-		m_freem(n);
-		return key_senderror(so, m, ENOBUFS);
-	}
 
-	if (n->m_len < sizeof(struct sadb_msg)) {
-		n = m_pullup(n, sizeof(struct sadb_msg));
-		if (n == NULL)
-			return key_sendup_mbuf(so, m, KEY_SENDUP_ONE);
-	}
+	KASSERT(n->m_len >= sizeof(struct sadb_msg));
 
 	n->m_pkthdr.len = 0;
 	for (nn = n; nn; nn = nn->m_next)
 		n->m_pkthdr.len += nn->m_len;
 
 	key_fill_replymsg(n, newsav->seq);
-
 	m_freem(m);
 	return key_sendup_mbuf(so, n, KEY_SENDUP_ONE);
     }
@@ -5970,7 +5834,7 @@ key_setident(struct secashead *sah, stru
 }
 
 /*
- * m will not be freed on return.
+ * m will not be freed on return. It never return NULL.
  * it is caller's responsibility to free the result.
  */
 static struct mbuf *
@@ -5991,14 +5855,9 @@ key_getmsgbuf_x1(struct mbuf *m, const s
 	    SADB_X_EXT_NAT_T_TYPE, SADB_X_EXT_NAT_T_SPORT,
 	    SADB_X_EXT_NAT_T_DPORT, SADB_X_EXT_NAT_T_OAI,
 	    SADB_X_EXT_NAT_T_OAR, SADB_X_EXT_NAT_T_FRAG);
-	if (!n)
-		return NULL;
 
-	if (n->m_len < sizeof(struct sadb_msg)) {
-		n = m_pullup(n, sizeof(struct sadb_msg));
-		if (n == NULL)
-			return NULL;
-	}
+	KASSERT(n->m_len >= sizeof(struct sadb_msg));
+
 	mtod(n, struct sadb_msg *)->sadb_msg_errno = 0;
 	mtod(n, struct sadb_msg *)->sadb_msg_len =
 	    PFKEY_UNIT64(n->m_pkthdr.len);
@@ -6098,13 +5957,8 @@ key_api_delete(struct socket *so, struct
 	/* create new sadb_msg to reply. */
 	n = key_gather_mbuf(m, mhp, 1, 4, SADB_EXT_RESERVED,
 	    SADB_EXT_SA, SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST);
-	if (!n)
-		return key_senderror(so, m, ENOBUFS);
-
-	n = key_fill_replymsg(n, 0);
-	if (n == NULL)
-		return key_senderror(so, m, ENOBUFS);
 
+	key_fill_replymsg(n, 0);
 	m_freem(m);
 	return key_sendup_mbuf(so, n, KEY_SENDUP_ALL);
     }
@@ -6160,13 +6014,8 @@ key_delete_all(struct socket *so, struct
 	/* create new sadb_msg to reply. */
 	n = key_gather_mbuf(m, mhp, 1, 3, SADB_EXT_RESERVED,
 	    SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST);
-	if (!n)
-		return key_senderror(so, m, ENOBUFS);
-
-	n = key_fill_replymsg(n, 0);
-	if (n == NULL)
-		return key_senderror(so, m, ENOBUFS);
 
+	key_fill_replymsg(n, 0);
 	m_freem(m);
 	return key_sendup_mbuf(so, n, KEY_SENDUP_ALL);
     }
@@ -6259,9 +6108,6 @@ key_api_get(struct socket *so, struct mb
 	n = key_setdumpsa(sav, SADB_GET, satype, mhp->msg->sadb_msg_seq,
 	    mhp->msg->sadb_msg_pid);
 	KEY_SA_UNREF(&sav);
-	if (!n)
-		return key_senderror(so, m, ENOBUFS);
-
 	m_freem(m);
 	return key_sendup_mbuf(so, n, KEY_SENDUP_ONE);
     }
@@ -6287,7 +6133,7 @@ key_getcomb_setlifetime(struct sadb_comb
  * XXX no idea if the user wants ESP authentication or not
  */
 static struct mbuf *
-key_getcomb_esp(void)
+key_getcomb_esp(int mflag)
 {
 	struct sadb_comb *comb;
 	const struct enc_xform *algo;
@@ -6312,11 +6158,11 @@ key_getcomb_esp(void)
 			encmin = _BITS(algo->minkey);
 
 		if (ipsec_esp_auth)
-			m = key_getcomb_ah();
+			m = key_getcomb_ah(mflag);
 		else {
 			KASSERTMSG(l <= MLEN,
 			    "l=%u > MLEN=%lu", l, (u_long) MLEN);
-			MGET(m, M_DONTWAIT, MT_DATA);
+			MGET(m, mflag, MT_DATA);
 			if (m) {
 				M_ALIGN(m, l);
 				m->m_len = l;
@@ -6385,7 +6231,7 @@ key_getsizes_ah(const struct auth_hash *
  * XXX reorder combinations by preference
  */
 static struct mbuf *
-key_getcomb_ah(void)
+key_getcomb_ah(int mflag)
 {
 	struct sadb_comb *comb;
 	const struct auth_hash *algo;
@@ -6416,14 +6262,14 @@ key_getcomb_ah(void)
 		if (!m) {
 			KASSERTMSG(l <= MLEN,
 			    "l=%u > MLEN=%lu", l, (u_long) MLEN);
-			MGET(m, M_DONTWAIT, MT_DATA);
+			MGET(m, mflag, MT_DATA);
 			if (m) {
 				M_ALIGN(m, l);
 				m->m_len = l;
 				m->m_next = NULL;
 			}
 		} else
-			M_PREPEND(m, l, M_DONTWAIT);
+			M_PREPEND(m, l, mflag);
 		if (!m)
 			return NULL;
 
@@ -6449,7 +6295,7 @@ key_getcomb_ah(void)
  * XXX reorder combinations by preference
  */
 static struct mbuf *
-key_getcomb_ipcomp(void)
+key_getcomb_ipcomp(int mflag)
 {
 	struct sadb_comb *comb;
 	const struct comp_algo *algo;
@@ -6466,14 +6312,14 @@ key_getcomb_ipcomp(void)
 		if (!m) {
 			KASSERTMSG(l <= MLEN,
 			    "l=%u > MLEN=%lu", l, (u_long) MLEN);
-			MGET(m, M_DONTWAIT, MT_DATA);
+			MGET(m, mflag, MT_DATA);
 			if (m) {
 				M_ALIGN(m, l);
 				m->m_len = l;
 				m->m_next = NULL;
 			}
 		} else
-			M_PREPEND(m, l, M_DONTWAIT);
+			M_PREPEND(m, l, mflag);
 		if (!m)
 			return NULL;
 
@@ -6499,7 +6345,7 @@ key_getcomb_ipcomp(void)
  * XXX sysctl interface to ipsec_{ah,esp}_keymin
  */
 static struct mbuf *
-key_getprop(const struct secasindex *saidx)
+key_getprop(const struct secasindex *saidx, int mflag)
 {
 	struct sadb_prop *prop;
 	struct mbuf *m, *n;
@@ -6508,13 +6354,13 @@ key_getprop(const struct secasindex *sai
 
 	switch (saidx->proto)  {
 	case IPPROTO_ESP:
-		m = key_getcomb_esp();
+		m = key_getcomb_esp(mflag);
 		break;
 	case IPPROTO_AH:
-		m = key_getcomb_ah();
+		m = key_getcomb_ah(mflag);
 		break;
 	case IPPROTO_IPCOMP:
-		m = key_getcomb_ipcomp();
+		m = key_getcomb_ipcomp(mflag);
 		break;
 	default:
 		return NULL;
@@ -6522,7 +6368,7 @@ key_getprop(const struct secasindex *sai
 
 	if (!m)
 		return NULL;
-	M_PREPEND(m, l, M_DONTWAIT);
+	M_PREPEND(m, l, mflag);
 	if (!m)
 		return NULL;
 
@@ -6560,7 +6406,7 @@ key_getprop(const struct secasindex *sai
  *    others: error number
  */
 static int
-key_acquire(const struct secasindex *saidx, const struct secpolicy *sp)
+key_acquire(const struct secasindex *saidx, const struct secpolicy *sp, int mflag)
 {
 	struct mbuf *result = NULL, *m;
 #ifndef IPSEC_NONBLOCK_ACQUIRE
@@ -6612,7 +6458,7 @@ key_acquire(const struct secasindex *sai
 #else
 	seq = (acq_seq = (acq_seq == ~0 ? 1 : ++acq_seq));
 #endif
-	m = key_setsadbmsg(SADB_ACQUIRE, 0, satype, seq, 0, 0);
+	m = key_setsadbmsg(SADB_ACQUIRE, 0, satype, seq, 0, 0, mflag);
 	if (!m) {
 		error = ENOBUFS;
 		goto fail;
@@ -6621,7 +6467,7 @@ key_acquire(const struct secasindex *sai
 
 	/* set sadb_address for saidx's. */
 	m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC, &saidx->src.sa, FULLMASK,
-	    IPSEC_ULPROTO_ANY);
+	    IPSEC_ULPROTO_ANY, mflag);
 	if (!m) {
 		error = ENOBUFS;
 		goto fail;
@@ -6629,7 +6475,7 @@ key_acquire(const struct secasindex *sai
 	m_cat(result, m);
 
 	m = key_setsadbaddr(SADB_EXT_ADDRESS_DST, &saidx->dst.sa, FULLMASK,
-	    IPSEC_ULPROTO_ANY);
+	    IPSEC_ULPROTO_ANY, mflag);
 	if (!m) {
 		error = ENOBUFS;
 		goto fail;
@@ -6640,7 +6486,8 @@ key_acquire(const struct secasindex *sai
 
 	/* set sadb_x_policy */
 	if (sp) {
-		m = key_setsadbxpolicy(sp->policy, sp->spidx.dir, sp->id);
+		m = key_setsadbxpolicy(sp->policy, sp->spidx.dir, sp->id,
+		    mflag);
 		if (!m) {
 			error = ENOBUFS;
 			goto fail;
@@ -6692,7 +6539,7 @@ key_acquire(const struct secasindex *sai
 	/* XXX sensitivity (optional) */
 
 	/* create proposal/combination extension */
-	m = key_getprop(saidx);
+	m = key_getprop(saidx, mflag);
 #if 0
 	/*
 	 * spec conformant: always attach proposal/combination extension,
@@ -6712,18 +6559,8 @@ key_acquire(const struct secasindex *sai
 		m_cat(result, m);
 #endif
 
-	if ((result->m_flags & M_PKTHDR) == 0) {
-		error = EINVAL;
-		goto fail;
-	}
-
-	if (result->m_len < sizeof(struct sadb_msg)) {
-		result = m_pullup(result, sizeof(struct sadb_msg));
-		if (result == NULL) {
-			error = ENOBUFS;
-			goto fail;
-		}
-	}
+	KASSERT(result->m_flags & M_PKTHDR);
+	KASSERT(result->m_len >= sizeof(struct sadb_msg));
 
 	result->m_pkthdr.len = 0;
 	for (m = result; m; m = m->m_next)
@@ -6733,6 +6570,12 @@ key_acquire(const struct secasindex *sai
 	    PFKEY_UNIT64(result->m_pkthdr.len);
 
 	/*
+	 * Called from key_api_acquire that must come from userland, so
+	 * we can call key_sendup_mbuf immediately.
+	 */
+	if (mflag == M_WAITOK)
+		return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED);
+	/*
 	 * XXX we cannot call key_sendup_mbuf directly here because
 	 * it can cause a deadlock:
 	 * - We have a reference to an SP (and an SA) here
@@ -7017,7 +6860,7 @@ key_api_acquire(struct socket *so, struc
 	pserialize_read_exit(s);
     }
 
-	error = key_acquire(&saidx, NULL);
+	error = key_acquire(&saidx, NULL, M_WAITOK);
 	if (error != 0) {
 		IPSECLOG(LOG_DEBUG, "error %d returned from key_acquire.\n",
 		    error);
@@ -7105,25 +6948,13 @@ key_api_register(struct socket *so, stru
 	if (len > MCLBYTES)
 		return key_senderror(so, m, ENOBUFS);
 
-	MGETHDR(n, M_DONTWAIT, MT_DATA);
-	if (len > MHLEN) {
-		MCLGET(n, M_DONTWAIT);
-		if ((n->m_flags & M_EXT) == 0) {
-			m_freem(n);
-			n = NULL;
-		}
-	}
-	if (!n)
-		return key_senderror(so, m, ENOBUFS);
-
+	n = key_alloc_mbuf_simple(len, M_WAITOK);
 	n->m_pkthdr.len = n->m_len = len;
 	n->m_next = NULL;
 	off = 0;
 
 	m_copydata(m, 0, sizeof(struct sadb_msg), mtod(n, char *) + off);
-	n = key_fill_replymsg(n, 0);
-	if (n == NULL)
-		return key_senderror(so, m, ENOBUFS);
+	key_fill_replymsg(n, 0);
 
 	off += PFKEY_ALIGN8(sizeof(struct sadb_msg));
 
@@ -7243,39 +7074,24 @@ key_expire(struct secasvar *sav)
 	KASSERTMSG(satype != 0, "invalid proto is passed");
 
 	/* set msg header */
-	m = key_setsadbmsg(SADB_EXPIRE, 0, satype, sav->seq, 0, key_sa_refcnt(sav));
-	if (!m) {
-		error = ENOBUFS;
-		goto fail;
-	}
+	m = key_setsadbmsg(SADB_EXPIRE, 0, satype, sav->seq, 0, key_sa_refcnt(sav),
+	    M_WAITOK);
 	result = m;
 
 	/* create SA extension */
 	m = key_setsadbsa(sav);
-	if (!m) {
-		error = ENOBUFS;
-		goto fail;
-	}
 	m_cat(result, m);
 
 	/* create SA extension */
 	m = key_setsadbxsa2(sav->sah->saidx.mode,
 	    sav->replay ? sav->replay->count : 0, sav->sah->saidx.reqid);
-	if (!m) {
-		error = ENOBUFS;
-		goto fail;
-	}
 	m_cat(result, m);
 
 	/* create lifetime extension (current and soft) */
 	len = PFKEY_ALIGN8(sizeof(*lt)) * 2;
-	m = key_alloc_mbuf(len);
-	if (!m || m->m_next) {	/*XXX*/
-		if (m)
-			m_freem(m);
-		error = ENOBUFS;
-		goto fail;
-	}
+	m = key_alloc_mbuf(len, M_WAITOK);
+	KASSERT(m->m_next == NULL);
+
 	memset(mtod(m, void *), 0, len);
 	lt = mtod(m, struct sadb_lifetime *);
 	lt->sadb_lifetime_len = PFKEY_UNIT64(sizeof(struct sadb_lifetime));
@@ -7292,20 +7108,12 @@ key_expire(struct secasvar *sav)
 
 	/* set sadb_address for source */
 	m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC, &sav->sah->saidx.src.sa,
-	    FULLMASK, IPSEC_ULPROTO_ANY);
-	if (!m) {
-		error = ENOBUFS;
-		goto fail;
-	}
+	    FULLMASK, IPSEC_ULPROTO_ANY, M_WAITOK);
 	m_cat(result, m);
 
 	/* set sadb_address for destination */
 	m = key_setsadbaddr(SADB_EXT_ADDRESS_DST, &sav->sah->saidx.dst.sa,
-	    FULLMASK, IPSEC_ULPROTO_ANY);
-	if (!m) {
-		error = ENOBUFS;
-		goto fail;
-	}
+	    FULLMASK, IPSEC_ULPROTO_ANY, M_WAITOK);
 	m_cat(result, m);
 
 	if ((result->m_flags & M_PKTHDR) == 0) {
@@ -7476,12 +7284,6 @@ key_setdump_chain(u_int8_t req_satype, i
 			SAVLIST_WRITER_FOREACH(sav, sah, state) {
 				n = key_setdumpsa(sav, SADB_DUMP, satype,
 				    --cnt, pid);
-				if (!n) {
-					m_freem(m);
-					*errorp = ENOBUFS;
-					return (NULL);
-				}
-
 				if (!m)
 					m = n;
 				else
@@ -7728,18 +7530,8 @@ key_parse(struct mbuf *m, struct socket 
 	if (m->m_next) {
 		struct mbuf *n;
 
-		MGETHDR(n, M_DONTWAIT, MT_DATA);
-		if (n && m->m_pkthdr.len > MHLEN) {
-			MCLGET(n, M_DONTWAIT);
-			if ((n->m_flags & M_EXT) == 0) {
-				m_free(n);
-				n = NULL;
-			}
-		}
-		if (!n) {
-			m_freem(m);
-			return ENOBUFS;
-		}
+		n = key_alloc_mbuf_simple(m->m_pkthdr.len, M_WAITOK);
+
 		m_copydata(m, 0, m->m_pkthdr.len, mtod(n, void *));
 		n->m_pkthdr.len = n->m_len = m->m_pkthdr.len;
 		n->m_next = NULL;
@@ -8362,16 +8154,23 @@ key_sa_chgstate(struct secasvar *sav, u_
 
 /* XXX too much? */
 static struct mbuf *
-key_alloc_mbuf(int l)
+key_alloc_mbuf(int l, int mflag)
 {
 	struct mbuf *m = NULL, *n;
 	int len, t;
 
+	KASSERT(mflag == M_NOWAIT || (mflag == M_WAITOK && !cpu_softintr_p()));
+
 	len = l;
 	while (len > 0) {
-		MGET(n, M_DONTWAIT, MT_DATA);
-		if (n && len > MLEN)
-			MCLGET(n, M_DONTWAIT);
+		MGET(n, mflag, MT_DATA);
+		if (n && len > MLEN) {
+			MCLGET(n, mflag);
+			if ((n->m_flags & M_EXT) == 0) {
+				m_freem(n);
+				n = NULL;
+			}
+		}
 		if (!n) {
 			m_freem(m);
 			return NULL;
@@ -8456,12 +8255,6 @@ key_setdump(u_int8_t req_satype, int *er
 			SAVLIST_WRITER_FOREACH(sav, sah, state) {
 				n = key_setdumpsa(sav, SADB_DUMP, satype,
 				    --cnt, pid);
-				if (!n) {
-					m_freem(m);
-					*errorp = ENOBUFS;
-					return (NULL);
-				}
-
 				if (!m)
 					m = n;
 				else
@@ -8514,11 +8307,6 @@ key_setspddump(int *errorp, pid_t pid)
 			--cnt;
 			n = key_setdumpsp(sp, SADB_X_SPDDUMP, cnt, pid);
 
-			if (!n) {
-				*errorp = ENOBUFS;
-				m_freem(m);
-				return (NULL);
-			}
 			if (!m)
 				m = n;
 			else {

Index: src/sys/netipsec/key.h
diff -u src/sys/netipsec/key.h:1.19.2.1 src/sys/netipsec/key.h:1.19.2.2
--- src/sys/netipsec/key.h:1.19.2.1	Sat Oct 21 19:43:54 2017
+++ src/sys/netipsec/key.h	Thu Nov 30 14:57:34 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: key.h,v 1.19.2.1 2017/10/21 19:43:54 snj Exp $	*/
+/*	$NetBSD: key.h,v 1.19.2.2 2017/11/30 14:57:34 martin Exp $	*/
 /*	$FreeBSD: src/sys/netipsec/key.h,v 1.1.4.1 2003/01/24 05:11:36 sam Exp $	*/
 /*	$KAME: key.h,v 1.21 2001/07/27 03:51:30 itojun Exp $	*/
 
@@ -101,7 +101,7 @@ int key_checkrequest(const struct ipsecr
     struct secasvar **);
 
 struct secpolicy *key_msg2sp (const struct sadb_x_policy *, size_t, int *);
-struct mbuf *key_sp2msg (const struct secpolicy *);
+struct mbuf *key_sp2msg(const struct secpolicy *, int);
 int key_ismyaddr (const struct sockaddr *);
 int key_spdacquire (const struct secpolicy *);
 u_long key_random (void);

Reply via email to