xfrm: Provide API to register translator module
Add a skeleton for xfrm_compat module and provide API to register it in xfrm_state.ko. struct xfrm_translator will have function pointers to translate messages received from 32-bit userspace or to be sent to it from 64-bit kernel. module_get()/module_put() are used instead of rcu_read_lock() as the module will vmalloc() memory for translation. The new API is registered with xfrm_state module, not with xfrm_user as the former needs translator for user_policy set by setsockopt() and xfrm_user already uses functions from xfrm_state. Signed-off-by: Dmitry Safonov <dima@arista.com> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
This commit is contained in:

committed by
Steffen Klassert

parent
02a20d4fef
commit
c9e7c76d70
@@ -2264,6 +2264,66 @@ static bool km_is_alive(const struct km_event *c)
|
||||
return is_alive;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_XFRM_USER_COMPAT)
|
||||
static DEFINE_SPINLOCK(xfrm_translator_lock);
|
||||
static struct xfrm_translator __rcu *xfrm_translator;
|
||||
|
||||
struct xfrm_translator *xfrm_get_translator(void)
|
||||
{
|
||||
struct xfrm_translator *xtr;
|
||||
|
||||
rcu_read_lock();
|
||||
xtr = rcu_dereference(xfrm_translator);
|
||||
if (unlikely(!xtr))
|
||||
goto out;
|
||||
if (!try_module_get(xtr->owner))
|
||||
xtr = NULL;
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
return xtr;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xfrm_get_translator);
|
||||
|
||||
void xfrm_put_translator(struct xfrm_translator *xtr)
|
||||
{
|
||||
module_put(xtr->owner);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xfrm_put_translator);
|
||||
|
||||
int xfrm_register_translator(struct xfrm_translator *xtr)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
spin_lock_bh(&xfrm_translator_lock);
|
||||
if (unlikely(xfrm_translator != NULL))
|
||||
err = -EEXIST;
|
||||
else
|
||||
rcu_assign_pointer(xfrm_translator, xtr);
|
||||
spin_unlock_bh(&xfrm_translator_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xfrm_register_translator);
|
||||
|
||||
int xfrm_unregister_translator(struct xfrm_translator *xtr)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
spin_lock_bh(&xfrm_translator_lock);
|
||||
if (likely(xfrm_translator != NULL)) {
|
||||
if (rcu_access_pointer(xfrm_translator) != xtr)
|
||||
err = -EINVAL;
|
||||
else
|
||||
RCU_INIT_POINTER(xfrm_translator, NULL);
|
||||
}
|
||||
spin_unlock_bh(&xfrm_translator_lock);
|
||||
synchronize_rcu();
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xfrm_unregister_translator);
|
||||
#endif
|
||||
|
||||
int xfrm_user_policy(struct sock *sk, int optname, sockptr_t optval, int optlen)
|
||||
{
|
||||
int err;
|
||||
|
Reference in New Issue
Block a user