mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-15 21:05:08 +00:00
Fix witness warning in xform_init().
Do not call crypto_newsession() while holding xforms_lock mutex. Release mutex before invoking crypto_newsession(), and use ipsec_kmod_enter()/ipsec_kmod_exit() functions to protect from doing access to unloaded kernel module memory. Move xform-releated functions into subr_ipsec.c to be able use ipsec_kmod_* functions. Also unconditionally build ipsec_kmod_* functions, since now they are always used by IPSec code. Add xf_cntr field to struct xformsw, it is used by ipsec_kmod_* functions. Also constify xf_name field, since it is not expected to be modified. Approved by: re (kib) Differential Revision: https://reviews.freebsd.org/D17302
This commit is contained in:
parent
6f282e722e
commit
0ddfd867ed
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=338945
|
@ -534,14 +534,6 @@ MALLOC_DEFINE(M_IPSEC_SPDCACHE, "ipsec-spdcache", "ipsec SPD cache");
|
|||
VNET_DEFINE_STATIC(uma_zone_t, key_lft_zone);
|
||||
#define V_key_lft_zone VNET(key_lft_zone)
|
||||
|
||||
static LIST_HEAD(xforms_list, xformsw) xforms = LIST_HEAD_INITIALIZER();
|
||||
static struct mtx xforms_lock;
|
||||
#define XFORMS_LOCK_INIT() \
|
||||
mtx_init(&xforms_lock, "xforms_list", "IPsec transforms list", MTX_DEF)
|
||||
#define XFORMS_LOCK_DESTROY() mtx_destroy(&xforms_lock)
|
||||
#define XFORMS_LOCK() mtx_lock(&xforms_lock)
|
||||
#define XFORMS_UNLOCK() mtx_unlock(&xforms_lock)
|
||||
|
||||
/*
|
||||
* set parameters into secpolicyindex buffer.
|
||||
* Must allocate secpolicyindex buffer passed to this function.
|
||||
|
@ -717,7 +709,6 @@ static int key_delete(struct socket *, struct mbuf *,
|
|||
const struct sadb_msghdr *);
|
||||
static int key_delete_all(struct socket *, struct mbuf *,
|
||||
const struct sadb_msghdr *, struct secasindex *);
|
||||
static void key_delete_xform(const struct xformsw *);
|
||||
static int key_get(struct socket *, struct mbuf *,
|
||||
const struct sadb_msghdr *);
|
||||
|
||||
|
@ -750,7 +741,6 @@ static int key_validate_ext(const struct sadb_ext *, int);
|
|||
static int key_align(struct mbuf *, struct sadb_msghdr *);
|
||||
static struct mbuf *key_setlifetime(struct seclifetime *, uint16_t);
|
||||
static struct mbuf *key_setkey(struct seckey *, uint16_t);
|
||||
static int xform_init(struct secasvar *, u_short);
|
||||
|
||||
static void spdcache_init(void);
|
||||
static void spdcache_clear(void);
|
||||
|
@ -6167,7 +6157,7 @@ key_delete_all(struct socket *so, struct mbuf *m,
|
|||
* Larval SAs have not initialized tdb_xform, so it is safe to leave them
|
||||
* here when xform disappears.
|
||||
*/
|
||||
static void
|
||||
void
|
||||
key_delete_xform(const struct xformsw *xsp)
|
||||
{
|
||||
struct secasvar_queue drainq;
|
||||
|
@ -8335,7 +8325,6 @@ key_init(void)
|
|||
if (!IS_DEFAULT_VNET(curvnet))
|
||||
return;
|
||||
|
||||
XFORMS_LOCK_INIT();
|
||||
SPTREE_LOCK_INIT();
|
||||
REGTREE_LOCK_INIT();
|
||||
SAHTREE_LOCK_INIT();
|
||||
|
@ -8458,7 +8447,6 @@ key_destroy(void)
|
|||
#ifndef IPSEC_DEBUG2
|
||||
callout_drain(&key_timer);
|
||||
#endif
|
||||
XFORMS_LOCK_DESTROY();
|
||||
SPTREE_LOCK_DESTROY();
|
||||
REGTREE_LOCK_DESTROY();
|
||||
SAHTREE_LOCK_DESTROY();
|
||||
|
@ -8617,70 +8605,3 @@ comp_algorithm_lookup(int alg)
|
|||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Register a transform.
|
||||
*/
|
||||
static int
|
||||
xform_register(struct xformsw* xsp)
|
||||
{
|
||||
struct xformsw *entry;
|
||||
|
||||
XFORMS_LOCK();
|
||||
LIST_FOREACH(entry, &xforms, chain) {
|
||||
if (entry->xf_type == xsp->xf_type) {
|
||||
XFORMS_UNLOCK();
|
||||
return (EEXIST);
|
||||
}
|
||||
}
|
||||
LIST_INSERT_HEAD(&xforms, xsp, chain);
|
||||
XFORMS_UNLOCK();
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
xform_attach(void *data)
|
||||
{
|
||||
struct xformsw *xsp = (struct xformsw *)data;
|
||||
|
||||
if (xform_register(xsp) != 0)
|
||||
printf("%s: failed to register %s xform\n", __func__,
|
||||
xsp->xf_name);
|
||||
}
|
||||
|
||||
void
|
||||
xform_detach(void *data)
|
||||
{
|
||||
struct xformsw *xsp = (struct xformsw *)data;
|
||||
|
||||
XFORMS_LOCK();
|
||||
LIST_REMOVE(xsp, chain);
|
||||
XFORMS_UNLOCK();
|
||||
|
||||
/* Delete all SAs related to this xform. */
|
||||
key_delete_xform(xsp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize transform support in an sav.
|
||||
*/
|
||||
static int
|
||||
xform_init(struct secasvar *sav, u_short xftype)
|
||||
{
|
||||
struct xformsw *entry;
|
||||
int ret;
|
||||
|
||||
IPSEC_ASSERT(sav->tdb_xform == NULL,
|
||||
("tdb_xform is already initialized"));
|
||||
|
||||
ret = EINVAL;
|
||||
XFORMS_LOCK();
|
||||
LIST_FOREACH(entry, &xforms, chain) {
|
||||
if (entry->xf_type == xftype) {
|
||||
ret = (*entry->xf_init)(sav, entry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
XFORMS_UNLOCK();
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ struct sadb_msg;
|
|||
struct sadb_x_policy;
|
||||
struct secasindex;
|
||||
union sockaddr_union;
|
||||
struct xformsw;
|
||||
|
||||
struct secpolicy *key_newsp(void);
|
||||
struct secpolicy *key_allocsp(struct secpolicyindex *, u_int);
|
||||
|
@ -74,6 +75,8 @@ int key_sockaddrcmp_withmask(const struct sockaddr *, const struct sockaddr *,
|
|||
int key_register_ifnet(struct secpolicy **, u_int);
|
||||
void key_unregister_ifnet(struct secpolicy **, u_int);
|
||||
|
||||
void key_delete_xform(const struct xformsw *);
|
||||
|
||||
extern u_long key_random(void);
|
||||
extern void key_randomfill(void *, size_t);
|
||||
extern void key_freereg(struct socket *);
|
||||
|
|
|
@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
|
|||
#include <netipsec/ipsec6.h>
|
||||
#include <netipsec/key.h>
|
||||
#include <netipsec/key_debug.h>
|
||||
#include <netipsec/xform.h>
|
||||
|
||||
#include <machine/atomic.h>
|
||||
/*
|
||||
|
@ -124,14 +125,6 @@ ipsec6_setsockaddrs(const struct mbuf *m, union sockaddr_union *src,
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef IPSEC_SUPPORT
|
||||
/*
|
||||
* IPSEC_SUPPORT - loading of ipsec.ko and tcpmd5.ko is supported.
|
||||
* IPSEC + IPSEC_SUPPORT - loading tcpmd5.ko is supported.
|
||||
* IPSEC + TCP_SIGNATURE - all is build in the kernel, do not build
|
||||
* IPSEC_SUPPORT.
|
||||
*/
|
||||
#if !defined(IPSEC) || !defined(TCP_SIGNATURE)
|
||||
#define IPSEC_MODULE_INCR 2
|
||||
static int
|
||||
ipsec_kmod_enter(volatile u_int *cntr)
|
||||
|
@ -171,6 +164,83 @@ ipsec_kmod_drain(volatile u_int *cntr)
|
|||
pause("ipsecd", hz/2);
|
||||
}
|
||||
|
||||
static LIST_HEAD(xforms_list, xformsw) xforms = LIST_HEAD_INITIALIZER();
|
||||
static struct mtx xforms_lock;
|
||||
MTX_SYSINIT(xfroms_list, &xforms_lock, "IPsec transforms list", MTX_DEF);
|
||||
#define XFORMS_LOCK() mtx_lock(&xforms_lock)
|
||||
#define XFORMS_UNLOCK() mtx_unlock(&xforms_lock)
|
||||
|
||||
void
|
||||
xform_attach(void *data)
|
||||
{
|
||||
struct xformsw *xsp, *entry;
|
||||
|
||||
xsp = (struct xformsw *)data;
|
||||
XFORMS_LOCK();
|
||||
LIST_FOREACH(entry, &xforms, chain) {
|
||||
if (entry->xf_type == xsp->xf_type) {
|
||||
XFORMS_UNLOCK();
|
||||
printf("%s: failed to register %s xform\n",
|
||||
__func__, xsp->xf_name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
LIST_INSERT_HEAD(&xforms, xsp, chain);
|
||||
xsp->xf_cntr = IPSEC_MODULE_ENABLED;
|
||||
XFORMS_UNLOCK();
|
||||
}
|
||||
|
||||
void
|
||||
xform_detach(void *data)
|
||||
{
|
||||
struct xformsw *xsp = (struct xformsw *)data;
|
||||
|
||||
XFORMS_LOCK();
|
||||
LIST_REMOVE(xsp, chain);
|
||||
XFORMS_UNLOCK();
|
||||
|
||||
/* Delete all SAs related to this xform. */
|
||||
key_delete_xform(xsp);
|
||||
if (xsp->xf_cntr & IPSEC_MODULE_ENABLED)
|
||||
ipsec_kmod_drain(&xsp->xf_cntr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize transform support in an sav.
|
||||
*/
|
||||
int
|
||||
xform_init(struct secasvar *sav, u_short xftype)
|
||||
{
|
||||
struct xformsw *entry;
|
||||
int ret;
|
||||
|
||||
IPSEC_ASSERT(sav->tdb_xform == NULL,
|
||||
("tdb_xform is already initialized"));
|
||||
|
||||
XFORMS_LOCK();
|
||||
LIST_FOREACH(entry, &xforms, chain) {
|
||||
if (entry->xf_type == xftype) {
|
||||
ret = ipsec_kmod_enter(&entry->xf_cntr);
|
||||
XFORMS_UNLOCK();
|
||||
if (ret != 0)
|
||||
return (ret);
|
||||
ret = (*entry->xf_init)(sav, entry);
|
||||
ipsec_kmod_exit(&entry->xf_cntr);
|
||||
return (ret);
|
||||
}
|
||||
}
|
||||
XFORMS_UNLOCK();
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
#ifdef IPSEC_SUPPORT
|
||||
/*
|
||||
* IPSEC_SUPPORT - loading of ipsec.ko and tcpmd5.ko is supported.
|
||||
* IPSEC + IPSEC_SUPPORT - loading tcpmd5.ko is supported.
|
||||
* IPSEC + TCP_SIGNATURE - all is build in the kernel, do not build
|
||||
* IPSEC_SUPPORT.
|
||||
*/
|
||||
#if !defined(IPSEC) || !defined(TCP_SIGNATURE)
|
||||
#define METHOD_DECL(...) __VA_ARGS__
|
||||
#define METHOD_ARGS(...) __VA_ARGS__
|
||||
#define IPSEC_KMOD_METHOD(type, name, sc, method, decl, args) \
|
||||
|
|
|
@ -86,14 +86,16 @@ struct xform_data {
|
|||
#define XF_IPCOMP 6 /* IPCOMP */
|
||||
|
||||
struct xformsw {
|
||||
u_short xf_type; /* xform ID */
|
||||
char *xf_name; /* human-readable name */
|
||||
u_short xf_type; /* xform ID */
|
||||
const char *xf_name; /* human-readable name */
|
||||
int (*xf_init)(struct secasvar*, struct xformsw*); /* setup */
|
||||
int (*xf_zeroize)(struct secasvar*); /* cleanup */
|
||||
int (*xf_input)(struct mbuf*, struct secasvar*, /* input */
|
||||
int, int);
|
||||
int (*xf_output)(struct mbuf*, /* output */
|
||||
struct secpolicy *, struct secasvar *, u_int, int, int);
|
||||
|
||||
volatile u_int xf_cntr;
|
||||
LIST_ENTRY(xformsw) chain;
|
||||
};
|
||||
|
||||
|
@ -103,6 +105,7 @@ const struct comp_algo * comp_algorithm_lookup(int);
|
|||
|
||||
void xform_attach(void *);
|
||||
void xform_detach(void *);
|
||||
int xform_init(struct secasvar *, u_short);
|
||||
|
||||
struct cryptoini;
|
||||
/* XF_AH */
|
||||
|
|
Loading…
Reference in a new issue