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);