Locking and misc cleanups; most of which I've been running for >4 months:

o add locking
o strip irrelevant spl's
o split malloc types to better account for memory use
o remove unused IPSEC_NONBLOCK_ACQUIRE code
o remove dead code

Sponsored by:	FreeBSD Foundation
This commit is contained in:
Sam Leffler 2003-09-01 05:35:55 +00:00
parent ee6e0476d2
commit 6464079f10
10 changed files with 386 additions and 508 deletions

View File

@ -202,6 +202,8 @@ static int ipsec_get_policy __P((struct secpolicy *pcb_sp, struct mbuf **mp));
static void vshiftl __P((unsigned char *, int, int));
static size_t ipsec_hdrsiz __P((struct secpolicy *));
MALLOC_DEFINE(M_IPSEC_INPCB, "inpcbpolicy", "inpcb-resident ipsec policy");
/*
* Return a held reference to the default SP.
*/
@ -836,7 +838,7 @@ static void
ipsec_delpcbpolicy(p)
struct inpcbpolicy *p;
{
free(p, M_SECA);
free(p, M_IPSEC_INPCB);
}
/* initialize policy in PCB */
@ -852,7 +854,7 @@ ipsec_init_policy(so, pcb_sp)
panic("ipsec_init_policy: NULL pointer was passed.\n");
new = (struct inpcbpolicy *) malloc(sizeof(struct inpcbpolicy),
M_SECA, M_NOWAIT|M_ZERO);
M_IPSEC_INPCB, M_NOWAIT|M_ZERO);
if (new == NULL) {
ipseclog((LOG_DEBUG, "ipsec_init_policy: No more memory.\n"));
return ENOBUFS;
@ -909,6 +911,24 @@ ipsec_copy_policy(old, new)
return 0;
}
struct ipsecrequest *
ipsec_newisr(void)
{
struct ipsecrequest *p;
p = malloc(sizeof(struct ipsecrequest), M_IPSEC_SR, M_NOWAIT|M_ZERO);
if (p != NULL)
mtx_init(&p->lock, "ipsec request", NULL, MTX_DEF);
return p;
}
void
ipsec_delisr(struct ipsecrequest *p)
{
mtx_destroy(&p->lock);
free(p, M_IPSEC_SR);
}
/* deep-copy a policy in PCB */
static struct secpolicy *
ipsec_deepcopy_policy(src)
@ -932,13 +952,9 @@ ipsec_deepcopy_policy(src)
*/
q = &newchain;
for (p = src->req; p; p = p->next) {
*q = (struct ipsecrequest *)malloc(sizeof(struct ipsecrequest),
M_SECA, M_NOWAIT);
*q = ipsec_newisr();
if (*q == NULL)
goto fail;
bzero(*q, sizeof(**q));
(*q)->next = NULL;
(*q)->saidx.proto = p->saidx.proto;
(*q)->saidx.mode = p->saidx.mode;
(*q)->level = p->level;
@ -947,7 +963,6 @@ ipsec_deepcopy_policy(src)
bcopy(&p->saidx.src, &(*q)->saidx.src, sizeof((*q)->saidx.src));
bcopy(&p->saidx.dst, &(*q)->saidx.dst, sizeof((*q)->saidx.dst));
(*q)->sav = NULL;
(*q)->sp = dst;
q = &((*q)->next);
@ -963,7 +978,7 @@ ipsec_deepcopy_policy(src)
fail:
for (p = newchain; p; p = r) {
r = p->next;
free(p, M_SECA);
ipsec_delisr(p);
p = NULL;
}
return NULL;

View File

@ -71,6 +71,7 @@ struct secpolicyindex {
/* Security Policy Data Base */
struct secpolicy {
LIST_ENTRY(secpolicy) chain;
struct mtx lock;
u_int refcnt; /* reference count */
struct secpolicyindex spidx; /* selector */
@ -108,6 +109,7 @@ struct ipsecrequest {
struct secasvar *sav; /* place holder of SA for use */
struct secpolicy *sp; /* back pointer to SP */
struct mtx lock; /* to interlock updates */
};
/* security policy in PCB */
@ -322,6 +324,9 @@ extern int crypto_support;
/* for openbsd compatibility */
#define DPRINTF(x) do { if (ipsec_debug) printf x; } while (0)
extern struct ipsecrequest *ipsec_newisr(void);
extern void ipsec_delisr(struct ipsecrequest *);
struct tdb_ident;
extern struct secpolicy *ipsec_getpolicy __P((struct tdb_ident*, u_int));
struct inpcb;

View File

@ -108,7 +108,7 @@ ipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto)
union sockaddr_union dst_address;
struct secasvar *sav;
u_int32_t spi;
int s, error;
int error;
IPSEC_ISTAT(sproto, espstat.esps_input, ahstat.ahs_input,
ipcompstat.ipcomps_input);
@ -178,8 +178,6 @@ ipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto)
return EPFNOSUPPORT;
}
s = splnet();
/* NB: only pass dst since key_allocsa follows RFC2401 */
sav = KEY_ALLOCSA(&dst_address, sproto, spi);
if (sav == NULL) {
@ -189,7 +187,6 @@ ipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto)
(u_long) ntohl(spi), sproto));
IPSEC_ISTAT(sproto, espstat.esps_notdb, ahstat.ahs_notdb,
ipcompstat.ipcomps_notdb);
splx(s);
m_freem(m);
return ENOENT;
}
@ -202,7 +199,6 @@ ipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto)
IPSEC_ISTAT(sproto, espstat.esps_noxform, ahstat.ahs_noxform,
ipcompstat.ipcomps_noxform);
KEY_FREESAV(&sav);
splx(s);
m_freem(m);
return ENXIO;
}
@ -213,7 +209,6 @@ ipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto)
*/
error = (*sav->tdb_xform->xf_input)(m, sav, skip, protoff);
KEY_FREESAV(&sav);
splx(s);
return error;
}

View File

@ -345,12 +345,12 @@ ipsec4_process_packet(
struct secasindex saidx;
struct secasvar *sav;
struct ip *ip;
int s, error, i, off;
int error, i, off;
KASSERT(m != NULL, ("ipsec4_process_packet: null mbuf"));
KASSERT(isr != NULL, ("ipsec4_process_packet: null isr"));
s = splnet(); /* insure SA contents don't change */
mtx_lock(&isr->lock); /* insure SA contents don't change */
isr = ipsec_nextisr(m, isr, AF_INET, &saidx, &error);
if (isr == NULL)
@ -469,10 +469,10 @@ ipsec4_process_packet(
} else {
error = ipsec_process_done(m, isr);
}
splx(s);
mtx_unlock(&isr->lock);
return error;
bad:
splx(s);
mtx_unlock(&isr->lock);
if (m)
m_freem(m);
return error;

File diff suppressed because it is too large Load Diff

View File

@ -100,7 +100,14 @@ extern void key_sa_routechange __P((struct sockaddr *));
extern void key_sa_stir_iv __P((struct secasvar *));
#ifdef MALLOC_DECLARE
MALLOC_DECLARE(M_SECA);
MALLOC_DECLARE(M_IPSEC_SA);
MALLOC_DECLARE(M_IPSEC_SAH);
MALLOC_DECLARE(M_IPSEC_SP);
MALLOC_DECLARE(M_IPSEC_SR);
MALLOC_DECLARE(M_IPSEC_MISC);
MALLOC_DECLARE(M_IPSEC_SAQ);
MALLOC_DECLARE(M_IPSEC_SAR);
MALLOC_DECLARE(M_IPSEC_INPCB);
#endif /* MALLOC_DECLARE */
#endif /* defined(_KERNEL) */

View File

@ -83,6 +83,7 @@ struct comp_algo;
/* Security Association */
struct secasvar {
LIST_ENTRY(secasvar) chain;
struct mtx lock; /* update/access lock */
u_int refcnt; /* reference count */
u_int8_t state; /* Status of this Association */

View File

@ -738,7 +738,7 @@ ah_input_cb(struct cryptop *crp)
struct secasindex *saidx;
u_int8_t nxt;
caddr_t ptr;
int s, authsize;
int authsize;
crd = crp->crp_desc;
@ -750,8 +750,6 @@ ah_input_cb(struct cryptop *crp)
mtag = (struct m_tag *) tc->tc_ptr;
m = (struct mbuf *) crp->crp_buf;
s = splnet();
sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi);
if (sav == NULL) {
ahstat.ahs_notdb++;
@ -866,12 +864,11 @@ ah_input_cb(struct cryptop *crp)
IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff, mtag);
KEY_FREESAV(&sav);
splx(s);
return error;
bad:
if (sav)
KEY_FREESAV(&sav);
splx(s);
if (m != NULL)
m_freem(m);
if (tc != NULL)
@ -1123,7 +1120,7 @@ ah_output_cb(struct cryptop *crp)
struct secasvar *sav;
struct mbuf *m;
caddr_t ptr;
int s, err;
int err;
tc = (struct tdb_crypto *) crp->crp_opaque;
KASSERT(tc != NULL, ("ah_output_cb: null opaque data area!"));
@ -1132,9 +1129,8 @@ ah_output_cb(struct cryptop *crp)
ptr = (caddr_t) (tc + 1);
m = (struct mbuf *) crp->crp_buf;
s = splnet();
isr = tc->tc_isr;
mtx_lock(&isr->lock);
sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi);
if (sav == NULL) {
ahstat.ahs_notdb++;
@ -1151,7 +1147,7 @@ ah_output_cb(struct cryptop *crp)
if (crp->crp_etype == EAGAIN) {
KEY_FREESAV(&sav);
splx(s);
mtx_unlock(&isr->lock);
return crypto_dispatch(crp);
}
@ -1183,12 +1179,13 @@ ah_output_cb(struct cryptop *crp)
/* NB: m is reclaimed by ipsec_process_done. */
err = ipsec_process_done(m, isr);
KEY_FREESAV(&sav);
splx(s);
mtx_unlock(&isr->lock);
return err;
bad:
if (sav)
KEY_FREESAV(&sav);
splx(s);
mtx_unlock(&isr->lock);
if (m)
m_freem(m);
free(tc, M_XDATA);

View File

@ -447,7 +447,7 @@ static int
esp_input_cb(struct cryptop *crp)
{
u_int8_t lastthree[3], aalg[AH_HMAC_HASHLEN];
int s, hlen, skip, protoff, error;
int hlen, skip, protoff, error;
struct mbuf *m;
struct cryptodesc *crd;
struct auth_hash *esph;
@ -468,8 +468,6 @@ esp_input_cb(struct cryptop *crp)
mtag = (struct m_tag *) tc->tc_ptr;
m = (struct mbuf *) crp->crp_buf;
s = splnet();
sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi);
if (sav == NULL) {
espstat.esps_notdb++;
@ -497,7 +495,6 @@ esp_input_cb(struct cryptop *crp)
if (crp->crp_etype == EAGAIN) {
KEY_FREESAV(&sav);
splx(s);
return crypto_dispatch(crp);
}
@ -610,12 +607,10 @@ DPRINTF(("esp_input_cb: %x %x\n", lastthree[0], lastthree[1]));
IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff, mtag);
KEY_FREESAV(&sav);
splx(s);
return error;
bad:
if (sav)
KEY_FREESAV(&sav);
splx(s);
if (m != NULL)
m_freem(m);
if (tc != NULL)
@ -868,15 +863,14 @@ esp_output_cb(struct cryptop *crp)
struct ipsecrequest *isr;
struct secasvar *sav;
struct mbuf *m;
int s, err, error;
int err, error;
tc = (struct tdb_crypto *) crp->crp_opaque;
KASSERT(tc != NULL, ("esp_output_cb: null opaque data area!"));
m = (struct mbuf *) crp->crp_buf;
s = splnet();
isr = tc->tc_isr;
mtx_lock(&isr->lock);
sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi);
if (sav == NULL) {
espstat.esps_notdb++;
@ -897,7 +891,7 @@ esp_output_cb(struct cryptop *crp)
if (crp->crp_etype == EAGAIN) {
KEY_FREESAV(&sav);
splx(s);
mtx_unlock(&isr->lock);
return crypto_dispatch(crp);
}
@ -925,12 +919,13 @@ esp_output_cb(struct cryptop *crp)
/* NB: m is reclaimed by ipsec_process_done. */
err = ipsec_process_done(m, isr);
KEY_FREESAV(&sav);
splx(s);
mtx_unlock(&isr->lock);
return err;
bad:
if (sav)
KEY_FREESAV(&sav);
splx(s);
mtx_unlock(&isr->lock);
if (m)
m_freem(m);
free(tc, M_XDATA);

View File

@ -35,6 +35,8 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/socket.h>
#include <sys/kernel.h>
#include <sys/protosw.h>
@ -215,7 +217,7 @@ ipcomp_input_cb(struct cryptop *crp)
struct mbuf *m;
struct secasvar *sav;
struct secasindex *saidx;
int s, hlen = IPCOMP_HLENGTH, error, clen;
int hlen = IPCOMP_HLENGTH, error, clen;
u_int8_t nproto;
caddr_t addr;
@ -228,8 +230,6 @@ ipcomp_input_cb(struct cryptop *crp)
mtag = (struct mtag *) tc->tc_ptr;
m = (struct mbuf *) crp->crp_buf;
s = splnet();
sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi);
if (sav == NULL) {
ipcompstat.ipcomps_notdb++;
@ -252,7 +252,6 @@ ipcomp_input_cb(struct cryptop *crp)
if (crp->crp_etype == EAGAIN) {
KEY_FREESAV(&sav);
splx(s);
return crypto_dispatch(crp);
}
@ -306,12 +305,10 @@ ipcomp_input_cb(struct cryptop *crp)
IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff, NULL);
KEY_FREESAV(&sav);
splx(s);
return error;
bad:
if (sav)
KEY_FREESAV(&sav);
splx(s);
if (m)
m_freem(m);
if (tc != NULL)
@ -500,7 +497,7 @@ ipcomp_output_cb(struct cryptop *crp)
struct ipsecrequest *isr;
struct secasvar *sav;
struct mbuf *m;
int s, error, skip, rlen;
int error, skip, rlen;
tc = (struct tdb_crypto *) crp->crp_opaque;
KASSERT(tc != NULL, ("ipcomp_output_cb: null opaque data area!"));
@ -508,9 +505,8 @@ ipcomp_output_cb(struct cryptop *crp)
skip = tc->tc_skip;
rlen = crp->crp_ilen - skip;
s = splnet();
isr = tc->tc_isr;
mtx_lock(&isr->lock);
sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi);
if (sav == NULL) {
ipcompstat.ipcomps_notdb++;
@ -528,7 +524,7 @@ ipcomp_output_cb(struct cryptop *crp)
if (crp->crp_etype == EAGAIN) {
KEY_FREESAV(&sav);
splx(s);
mtx_unlock(&isr->lock);
return crypto_dispatch(crp);
}
ipcompstat.ipcomps_noxform++;
@ -581,12 +577,13 @@ ipcomp_output_cb(struct cryptop *crp)
/* NB: m is reclaimed by ipsec_process_done. */
error = ipsec_process_done(m, isr);
KEY_FREESAV(&sav);
splx(s);
mtx_unlock(&isr->lock);
return error;
bad:
if (sav)
KEY_FREESAV(&sav);
splx(s);
mtx_unlock(&isr->lock);
if (m)
m_freem(m);
free(tc, M_XDATA);