diff options
-rw-r--r-- | include/net/lwtunnel.h | 5 | ||||
-rw-r--r-- | net/core/lwtunnel.c | 14 |
2 files changed, 14 insertions, 5 deletions
diff --git a/include/net/lwtunnel.h b/include/net/lwtunnel.h index 3e0a7a942a0e..fc7c0dbdd1ff 100644 --- a/include/net/lwtunnel.h +++ b/include/net/lwtunnel.h @@ -48,10 +48,7 @@ struct lwtunnel_encap_ops { }; #ifdef CONFIG_LWTUNNEL -static inline void lwtstate_free(struct lwtunnel_state *lws) -{ - kfree(lws); -} +void lwtstate_free(struct lwtunnel_state *lws); static inline struct lwtunnel_state * lwtstate_get(struct lwtunnel_state *lws) diff --git a/net/core/lwtunnel.c b/net/core/lwtunnel.c index 2f6db386624e..afa64f086d87 100644 --- a/net/core/lwtunnel.c +++ b/net/core/lwtunnel.c @@ -66,6 +66,15 @@ EXPORT_SYMBOL(lwtunnel_state_alloc); static const struct lwtunnel_encap_ops __rcu * lwtun_encaps[LWTUNNEL_ENCAP_MAX + 1] __read_mostly; +void lwtstate_free(struct lwtunnel_state *lws) +{ + const struct lwtunnel_encap_ops *ops = lwtun_encaps[lws->type]; + + kfree(lws); + module_put(ops->owner); +} +EXPORT_SYMBOL(lwtstate_free); + int lwtunnel_encap_add_ops(const struct lwtunnel_encap_ops *ops, unsigned int num) { @@ -111,8 +120,11 @@ int lwtunnel_build_state(struct net_device *dev, u16 encap_type, ret = -EOPNOTSUPP; rcu_read_lock(); ops = rcu_dereference(lwtun_encaps[encap_type]); - if (likely(ops && ops->build_state)) + if (likely(ops && ops->build_state && try_module_get(ops->owner))) { ret = ops->build_state(dev, encap, family, cfg, lws); + if (ret) + module_put(ops->owner); + } rcu_read_unlock(); return ret; |