Module Name:    src
Committed By:   drochner
Date:           Thu Feb 10 20:24:27 UTC 2011

Modified Files:
        src/sys/netipsec: ipsec_output.c xform_ah.c xform_esp.c xform_ipcomp.c

Log Message:
-in opencrypto callbacks (which run in a kernel thread), pull softnet_lock
 everywhere splsoftnet() was used before, to fix MP concurrency problems
-pull KERNEL_LOCK where ip(6)_output() is called, as this is what
 the network stack (unfortunately) expects, in particular to avoid
 races for packets in the interface send queues
>From Wolfgang Stukenbrock per PR kern/44418, with the application
of KERNEL_LOCK to what I think are the essential points, tested
on a dual-core i386.


To generate a diff of this commit:
cvs rdiff -u -r1.29 -r1.30 src/sys/netipsec/ipsec_output.c
cvs rdiff -u -r1.26 -r1.27 src/sys/netipsec/xform_ah.c
cvs rdiff -u -r1.22 -r1.23 src/sys/netipsec/xform_esp.c
cvs rdiff -u -r1.20 -r1.21 src/sys/netipsec/xform_ipcomp.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/ipsec_output.c
diff -u src/sys/netipsec/ipsec_output.c:1.29 src/sys/netipsec/ipsec_output.c:1.30
--- src/sys/netipsec/ipsec_output.c:1.29	Tue Dec  1 01:01:34 2009
+++ src/sys/netipsec/ipsec_output.c	Thu Feb 10 20:24:27 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: ipsec_output.c,v 1.29 2009/12/01 01:01:34 dyoung Exp $	*/
+/*	$NetBSD: ipsec_output.c,v 1.30 2011/02/10 20:24:27 drochner Exp $	*/
 
 /*-
  * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ipsec_output.c,v 1.29 2009/12/01 01:01:34 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ipsec_output.c,v 1.30 2011/02/10 20:24:27 drochner Exp $");
 
 /*
  * IPsec output processing.
@@ -123,6 +123,9 @@
 #ifdef INET
 	struct ip * ip;
 #endif /* INET */
+#if defined(INET) || defined(INET6)
+	int rv;
+#endif
 
 	switch (af) {
 #ifdef INET
@@ -133,8 +136,11 @@
 		ip->ip_len = ntohs(ip->ip_len);
 		ip->ip_off = ntohs(ip->ip_off);
 #endif /* __FreeBSD_ */
-		return ip_output(m, NULL, NULL, IP_RAWOUTPUT,
+		KERNEL_LOCK(1, NULL);
+		rv = ip_output(m, NULL, NULL, IP_RAWOUTPUT,
 		    (struct ip_moptions *)NULL, (struct socket *)NULL);
+		KERNEL_UNLOCK_ONE(NULL);
+		return rv;
 
 #endif /* INET */
 #ifdef INET6
@@ -143,7 +149,10 @@
 		 * We don't need massage, IPv6 header fields are always in
 		 * net endian.
 		 */
-		return ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
+		KERNEL_LOCK(1, NULL);
+		rv = ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
+		KERNEL_UNLOCK_ONE(NULL);
+		return rv;
 #endif /* INET6 */
 	}
 

Index: src/sys/netipsec/xform_ah.c
diff -u src/sys/netipsec/xform_ah.c:1.26 src/sys/netipsec/xform_ah.c:1.27
--- src/sys/netipsec/xform_ah.c:1.26	Sat Apr 18 14:58:06 2009
+++ src/sys/netipsec/xform_ah.c	Thu Feb 10 20:24:27 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: xform_ah.c,v 1.26 2009/04/18 14:58:06 tsutsui Exp $	*/
+/*	$NetBSD: xform_ah.c,v 1.27 2011/02/10 20:24:27 drochner Exp $	*/
 /*	$FreeBSD: src/sys/netipsec/xform_ah.c,v 1.1.4.1 2003/01/24 05:11:36 sam Exp $	*/
 /*	$OpenBSD: ip_ah.c,v 1.63 2001/06/26 06:18:58 angelos Exp $ */
 /*
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xform_ah.c,v 1.26 2009/04/18 14:58:06 tsutsui Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xform_ah.c,v 1.27 2011/02/10 20:24:27 drochner Exp $");
 
 #include "opt_inet.h"
 #ifdef __FreeBSD__
@@ -53,6 +53,7 @@
 #include <sys/syslog.h>
 #include <sys/kernel.h>
 #include <sys/sysctl.h>
+#include <sys/socketvar.h> /* for softnet_lock */
 
 #include <net/if.h>
 
@@ -828,6 +829,7 @@
 	}
 #endif
 
+	mutex_enter(softnet_lock);
 	s = splsoftnet();
 
 	sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi, sport, dport);
@@ -851,8 +853,11 @@
 		if (sav->tdb_cryptoid != 0)
 			sav->tdb_cryptoid = crp->crp_sid;
 
-		if (crp->crp_etype == EAGAIN)
+		if (crp->crp_etype == EAGAIN) {
+			splx(s);
+			mutex_exit(softnet_lock);
 			return crypto_dispatch(crp);
+		}
 
 		AH_STATINC(AH_STAT_NOXFORM);
 		DPRINTF(("ah_input_cb: crypto error %d\n", crp->crp_etype));
@@ -960,11 +965,13 @@
 
 	KEY_FREESAV(&sav);
 	splx(s);
+	mutex_exit(softnet_lock);
 	return error;
 bad:
 	if (sav)
 		KEY_FREESAV(&sav);
 	splx(s);
+	mutex_exit(softnet_lock);
 	if (m != NULL)
 		m_freem(m);
 	if (tc != NULL)
@@ -1228,6 +1235,7 @@
 	ptr = (tc + 1);
 	m = (struct mbuf *) crp->crp_buf;
 
+	mutex_enter(softnet_lock);
 	s = splsoftnet();
 
 	isr = tc->tc_isr;
@@ -1248,6 +1256,7 @@
 		if (crp->crp_etype == EAGAIN) {
 			KEY_FREESAV(&sav);
 			splx(s);
+			mutex_exit(softnet_lock);
 			return crypto_dispatch(crp);
 		}
 
@@ -1294,11 +1303,13 @@
 	err = ipsec_process_done(m, isr);
 	KEY_FREESAV(&sav);
 	splx(s);
+	mutex_exit(softnet_lock);
 	return err;
 bad:
 	if (sav)
 		KEY_FREESAV(&sav);
 	splx(s);
+	mutex_exit(softnet_lock);
 	if (m)
 		m_freem(m);
 	free(tc, M_XDATA);

Index: src/sys/netipsec/xform_esp.c
diff -u src/sys/netipsec/xform_esp.c:1.22 src/sys/netipsec/xform_esp.c:1.23
--- src/sys/netipsec/xform_esp.c:1.22	Fri Mar 20 05:30:27 2009
+++ src/sys/netipsec/xform_esp.c	Thu Feb 10 20:24:27 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: xform_esp.c,v 1.22 2009/03/20 05:30:27 cegger Exp $	*/
+/*	$NetBSD: xform_esp.c,v 1.23 2011/02/10 20:24:27 drochner Exp $	*/
 /*	$FreeBSD: src/sys/netipsec/xform_esp.c,v 1.2.2.1 2003/01/24 05:11:36 sam Exp $	*/
 /*	$OpenBSD: ip_esp.c,v 1.69 2001/06/26 06:18:59 angelos Exp $ */
 
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xform_esp.c,v 1.22 2009/03/20 05:30:27 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xform_esp.c,v 1.23 2011/02/10 20:24:27 drochner Exp $");
 
 #include "opt_inet.h"
 #ifdef __FreeBSD__
@@ -54,6 +54,7 @@
 #include <sys/kernel.h>
 /*#include <sys/random.h>*/
 #include <sys/sysctl.h>
+#include <sys/socketvar.h> /* for softnet_lock */
 
 #include <net/if.h>
 
@@ -497,6 +498,7 @@
 	}
 #endif
 
+	mutex_enter(softnet_lock);
 	s = splsoftnet();
 
 	sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi, sport, dport);
@@ -527,6 +529,7 @@
 		if (crp->crp_etype == EAGAIN) {
 			KEY_FREESAV(&sav);
 			splx(s);
+			mutex_exit(softnet_lock);
 			return crypto_dispatch(crp);
 		}
 
@@ -665,11 +668,13 @@
 
 	KEY_FREESAV(&sav);
 	splx(s);
+	mutex_exit(softnet_lock);
 	return error;
 bad:
 	if (sav)
 		KEY_FREESAV(&sav);
 	splx(s);
+	mutex_exit(softnet_lock);
 	if (m != NULL)
 		m_freem(m);
 	if (tc != NULL)
@@ -934,6 +939,7 @@
 	IPSEC_ASSERT(tc != NULL, ("esp_output_cb: null opaque data area!"));
 	m = (struct mbuf *) crp->crp_buf;
 
+	mutex_enter(softnet_lock);
 	s = splsoftnet();
 
 	isr = tc->tc_isr;
@@ -958,6 +964,7 @@
 		if (crp->crp_etype == EAGAIN) {
 			KEY_FREESAV(&sav);
 			splx(s);
+			mutex_exit(softnet_lock);
 			return crypto_dispatch(crp);
 		}
 
@@ -1004,11 +1011,13 @@
 	err = ipsec_process_done(m, isr);
 	KEY_FREESAV(&sav);
 	splx(s);
+	mutex_exit(softnet_lock);
 	return err;
 bad:
 	if (sav)
 		KEY_FREESAV(&sav);
 	splx(s);
+	mutex_exit(softnet_lock);
 	if (m)
 		m_freem(m);
 	free(tc, M_XDATA);

Index: src/sys/netipsec/xform_ipcomp.c
diff -u src/sys/netipsec/xform_ipcomp.c:1.20 src/sys/netipsec/xform_ipcomp.c:1.21
--- src/sys/netipsec/xform_ipcomp.c:1.20	Tue Sep 21 13:41:18 2010
+++ src/sys/netipsec/xform_ipcomp.c	Thu Feb 10 20:24:27 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: xform_ipcomp.c,v 1.20 2010/09/21 13:41:18 degroote Exp $	*/
+/*	$NetBSD: xform_ipcomp.c,v 1.21 2011/02/10 20:24:27 drochner Exp $	*/
 /*	$FreeBSD: src/sys/netipsec/xform_ipcomp.c,v 1.1.4.1 2003/01/24 05:11:36 sam Exp $	*/
 /* $OpenBSD: ip_ipcomp.c,v 1.1 2001/07/05 12:08:52 jjbg Exp $ */
 
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xform_ipcomp.c,v 1.20 2010/09/21 13:41:18 degroote Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xform_ipcomp.c,v 1.21 2011/02/10 20:24:27 drochner Exp $");
 
 /* IP payload compression protocol (IPComp), see RFC 2393 */
 #include "opt_inet.h"
@@ -45,6 +45,7 @@
 #include <sys/kernel.h>
 #include <sys/protosw.h>
 #include <sys/sysctl.h>
+#include <sys/socketvar.h> /* for softnet_lock */
 
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
@@ -257,6 +258,7 @@
 	}
 #endif
 
+	mutex_enter(softnet_lock);
 	s = splsoftnet();
 
 	sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi, sport, dport);
@@ -282,6 +284,7 @@
 		if (crp->crp_etype == EAGAIN) {
 			KEY_FREESAV(&sav);
 			splx(s);
+			mutex_exit(softnet_lock);
 			return crypto_dispatch(crp);
 		}
 
@@ -340,11 +343,13 @@
 
 	KEY_FREESAV(&sav);
 	splx(s);
+	mutex_exit(softnet_lock);
 	return error;
 bad:
 	if (sav)
 		KEY_FREESAV(&sav);
 	splx(s);
+	mutex_exit(softnet_lock);
 	if (m)
 		m_freem(m);
 	if (tc != NULL)
@@ -513,6 +518,7 @@
 	skip = tc->tc_skip;
 	rlen = crp->crp_ilen - skip;
 
+	mutex_enter(softnet_lock);
 	s = splsoftnet();
 
 	isr = tc->tc_isr;
@@ -534,6 +540,7 @@
 		if (crp->crp_etype == EAGAIN) {
 			KEY_FREESAV(&sav);
 			splx(s);
+			mutex_exit(softnet_lock);
 			return crypto_dispatch(crp);
 		}
 		IPCOMP_STATINC(IPCOMP_STAT_NOXFORM);
@@ -629,11 +636,13 @@
 	error = ipsec_process_done(m, isr);
 	KEY_FREESAV(&sav);
 	splx(s);
+	mutex_exit(softnet_lock);
 	return error;
 bad:
 	if (sav)
 		KEY_FREESAV(&sav);
 	splx(s);
+	mutex_exit(softnet_lock);
 	if (m)
 		m_freem(m);
 	free(tc, M_XDATA);

Reply via email to