Add the check that current VNET is ready and access to srchash is

allowed.

ipsec_srcaddr() callback can be called during VNET teardown, since
ingress address checking subsystem isn't VNET specific. And thus
callback can make access to already freed memory. To prevent this,
use V_ipsec_idhtbl pointer as indicator of VNET readiness. And make
epoch_wait() after resetting it to NULL in vnet_ipsec_uninit() to
be sure that ipsec_srcaddr() is finished its work.

Reported by:	kp
MFC after:	20 days
This commit is contained in:
Andrey V. Elsukov 2018-10-23 13:03:03 +00:00
parent 5acedb55c0
commit 221022e190

View File

@ -273,6 +273,13 @@ vnet_ipsec_uninit(const void *unused __unused)
if_clone_detach(V_ipsec_cloner);
free(V_ipsec_idhtbl, M_IPSEC);
/*
* Use V_ipsec_idhtbl pointer as indicator that VNET is going to be
* destroyed, it is used by ipsec_srcaddr() callback.
*/
V_ipsec_idhtbl = NULL;
IPSEC_WAIT();
#ifdef INET
if (IS_DEFAULT_VNET(curvnet))
ip_encap_unregister_srcaddr(ipsec4_srctab);
@ -785,6 +792,10 @@ ipsec_srcaddr(void *arg __unused, const struct sockaddr *sa,
struct ipsec_softc *sc;
struct secasindex *saidx;
/* Check that VNET is ready */
if (V_ipsec_idhtbl == NULL)
return;
MPASS(in_epoch(net_epoch_preempt));
CK_LIST_FOREACH(sc, ipsec_srchash(sa), srchash) {
if (sc->family == 0)