1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-14 14:55:41 +00:00

Set the proper vnet in IPsec callback functions.

When using hardware crypto engines, the callback functions used to handle
an IPsec packet after it has been encrypted or decrypted can be invoked
asynchronously from a worker thread that is not associated with a vnet.
Extend 'struct xform_data' to include a vnet pointer and save the current
vnet in this new member when queueing crypto requests in IPsec.  In the
IPsec callback routines, use the new member to set the current vnet while
processing the modified packet.

This fixes a panic when using hardware offload such as ccr(4) with IPsec
after VIMAGE was enabled in GENERIC.

Reported by:	Sony Arpita Das and Harsh Jain @ Chelsio
Reviewed by:	bz
MFC after:	1 week
Sponsored by:	Chelsio Communications
Differential Revision:	https://reviews.freebsd.org/D14763
This commit is contained in:
John Baldwin 2018-03-20 17:05:23 +00:00
parent 79e9552ebb
commit fd40ecf3d4
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=331248
4 changed files with 31 additions and 0 deletions

View File

@ -76,6 +76,7 @@ struct xform_data {
int protoff; /* current protocol offset */
int skip; /* data offset */
uint8_t nxt; /* next protocol, e.g. IPV4 */
struct vnet *vnet;
};
#define XF_IP4 1 /* unused */

View File

@ -667,6 +667,7 @@ ah_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
xd->protoff = protoff;
xd->skip = skip;
xd->cryptoid = cryptoid;
xd->vnet = curvnet;
return (crypto_dispatch(crp));
bad:
m_freem(m);
@ -693,6 +694,7 @@ ah_input_cb(struct cryptop *crp)
m = (struct mbuf *) crp->crp_buf;
xd = (struct xform_data *) crp->crp_opaque;
CURVNET_SET(xd->vnet);
sav = xd->sav;
skip = xd->skip;
nxt = xd->nxt;
@ -710,6 +712,7 @@ ah_input_cb(struct cryptop *crp)
if (ipsec_updateid(sav, &crp->crp_sid, &cryptoid) != 0)
crypto_freesession(cryptoid);
xd->cryptoid = crp->crp_sid;
CURVNET_RESTORE();
return (crypto_dispatch(crp));
}
AHSTAT_INC(ahs_noxform);
@ -805,8 +808,10 @@ ah_input_cb(struct cryptop *crp)
panic("%s: Unexpected address family: %d saidx=%p", __func__,
saidx->dst.sa.sa_family, saidx);
}
CURVNET_RESTORE();
return error;
bad:
CURVNET_RESTORE();
if (sav)
key_freesav(&sav);
if (m != NULL)
@ -1040,6 +1045,7 @@ ah_output(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav,
xd->skip = skip;
xd->idx = idx;
xd->cryptoid = cryptoid;
xd->vnet = curvnet;
return crypto_dispatch(crp);
bad:
@ -1067,6 +1073,7 @@ ah_output_cb(struct cryptop *crp)
m = (struct mbuf *) crp->crp_buf;
xd = (struct xform_data *) crp->crp_opaque;
CURVNET_SET(xd->vnet);
sp = xd->sp;
sav = xd->sav;
skip = xd->skip;
@ -1081,6 +1088,7 @@ ah_output_cb(struct cryptop *crp)
if (ipsec_updateid(sav, &crp->crp_sid, &cryptoid) != 0)
crypto_freesession(cryptoid);
xd->cryptoid = crp->crp_sid;
CURVNET_RESTORE();
return (crypto_dispatch(crp));
}
AHSTAT_INC(ahs_noxform);
@ -1122,8 +1130,10 @@ ah_output_cb(struct cryptop *crp)
/* NB: m is reclaimed by ipsec_process_done. */
error = ipsec_process_done(m, sp, sav, idx);
CURVNET_RESTORE();
return (error);
bad:
CURVNET_RESTORE();
free(xd, M_XDATA);
crypto_freereq(crp);
key_freesav(&sav);

View File

@ -397,6 +397,7 @@ esp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
xd->protoff = protoff;
xd->skip = skip;
xd->cryptoid = cryptoid;
xd->vnet = curvnet;
/* Decryption descriptor */
IPSEC_ASSERT(crde != NULL, ("null esp crypto descriptor"));
@ -455,6 +456,7 @@ esp_input_cb(struct cryptop *crp)
m = (struct mbuf *) crp->crp_buf;
xd = (struct xform_data *) crp->crp_opaque;
CURVNET_SET(xd->vnet);
sav = xd->sav;
skip = xd->skip;
protoff = xd->protoff;
@ -469,6 +471,7 @@ esp_input_cb(struct cryptop *crp)
if (ipsec_updateid(sav, &crp->crp_sid, &cryptoid) != 0)
crypto_freesession(cryptoid);
xd->cryptoid = crp->crp_sid;
CURVNET_RESTORE();
return (crypto_dispatch(crp));
}
ESPSTAT_INC(esps_noxform);
@ -603,8 +606,10 @@ esp_input_cb(struct cryptop *crp)
panic("%s: Unexpected address family: %d saidx=%p", __func__,
saidx->dst.sa.sa_family, saidx);
}
CURVNET_RESTORE();
return error;
bad:
CURVNET_RESTORE();
if (sav != NULL)
key_freesav(&sav);
if (m != NULL)
@ -837,6 +842,7 @@ esp_output(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav,
xd->sav = sav;
xd->idx = idx;
xd->cryptoid = cryptoid;
xd->vnet = curvnet;
/* Crypto operation descriptor. */
crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */
@ -882,6 +888,7 @@ esp_output_cb(struct cryptop *crp)
int error;
xd = (struct xform_data *) crp->crp_opaque;
CURVNET_SET(xd->vnet);
m = (struct mbuf *) crp->crp_buf;
sp = xd->sp;
sav = xd->sav;
@ -895,6 +902,7 @@ esp_output_cb(struct cryptop *crp)
if (ipsec_updateid(sav, &crp->crp_sid, &cryptoid) != 0)
crypto_freesession(cryptoid);
xd->cryptoid = crp->crp_sid;
CURVNET_RESTORE();
return (crypto_dispatch(crp));
}
ESPSTAT_INC(esps_noxform);
@ -940,8 +948,10 @@ esp_output_cb(struct cryptop *crp)
/* NB: m is reclaimed by ipsec_process_done. */
error = ipsec_process_done(m, sp, sav, idx);
CURVNET_RESTORE();
return (error);
bad:
CURVNET_RESTORE();
free(xd, M_XDATA);
crypto_freereq(crp);
key_freesav(&sav);

View File

@ -255,6 +255,7 @@ ipcomp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
xd->sav = sav;
xd->protoff = protoff;
xd->skip = skip;
xd->vnet = curvnet;
SECASVAR_LOCK(sav);
crp->crp_sid = xd->cryptoid = sav->tdb_cryptoid;
@ -286,6 +287,7 @@ ipcomp_input_cb(struct cryptop *crp)
m = (struct mbuf *) crp->crp_buf;
xd = (struct xform_data *) crp->crp_opaque;
CURVNET_SET(xd->vnet);
sav = xd->sav;
skip = xd->skip;
protoff = xd->protoff;
@ -302,6 +304,7 @@ ipcomp_input_cb(struct cryptop *crp)
if (ipsec_updateid(sav, &crp->crp_sid, &cryptoid) != 0)
crypto_freesession(cryptoid);
xd->cryptoid = crp->crp_sid;
CURVNET_RESTORE();
return (crypto_dispatch(crp));
}
IPCOMPSTAT_INC(ipcomps_noxform);
@ -366,8 +369,10 @@ ipcomp_input_cb(struct cryptop *crp)
panic("%s: Unexpected address family: %d saidx=%p", __func__,
saidx->dst.sa.sa_family, saidx);
}
CURVNET_RESTORE();
return error;
bad:
CURVNET_RESTORE();
if (sav != NULL)
key_freesav(&sav);
if (m != NULL)
@ -493,6 +498,7 @@ ipcomp_output(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav,
xd->idx = idx;
xd->skip = skip;
xd->protoff = protoff;
xd->vnet = curvnet;
/* Crypto operation descriptor */
crp->crp_ilen = m->m_pkthdr.len; /* Total input length */
@ -531,6 +537,7 @@ ipcomp_output_cb(struct cryptop *crp)
m = (struct mbuf *) crp->crp_buf;
xd = (struct xform_data *) crp->crp_opaque;
CURVNET_SET(xd->vnet);
idx = xd->idx;
sp = xd->sp;
sav = xd->sav;
@ -545,6 +552,7 @@ ipcomp_output_cb(struct cryptop *crp)
if (ipsec_updateid(sav, &crp->crp_sid, &cryptoid) != 0)
crypto_freesession(cryptoid);
xd->cryptoid = crp->crp_sid;
CURVNET_RESTORE();
return (crypto_dispatch(crp));
}
IPCOMPSTAT_INC(ipcomps_noxform);
@ -640,10 +648,12 @@ ipcomp_output_cb(struct cryptop *crp)
/* NB: m is reclaimed by ipsec_process_done. */
error = ipsec_process_done(m, sp, sav, idx);
CURVNET_RESTORE();
return (error);
bad:
if (m)
m_freem(m);
CURVNET_RESTORE();
free(xd, M_XDATA);
crypto_freereq(crp);
key_freesav(&sav);