@@ -11,6 +11,7 @@
#include <linux/wait.h>
#include <linux/list.h>
#include <linux/static_key.h>
+#include <linux/module.h>
#include <linux/netfilter_defs.h>
#include <linux/netdevice.h>
#include <linux/sockptr.h>
@@ -482,12 +483,14 @@ struct nfnl_ct_hook {
extern const struct nfnl_ct_hook __rcu *nfnl_ct_hook;
struct nf_defrag_v4_hook {
+ struct module *owner;
int (*enable)(struct net *net);
void (*disable)(struct net *net);
};
extern const struct nf_defrag_v4_hook __rcu *nf_defrag_v4_hook;
struct nf_defrag_v6_hook {
+ struct module *owner;
int (*enable)(struct net *net);
void (*disable)(struct net *net);
};
@@ -115,6 +115,7 @@ static void __net_exit defrag4_net_exit(struct net *net)
}
static const struct nf_defrag_v4_hook defrag_hook = {
+ .owner = THIS_MODULE,
.enable = nf_defrag_ipv4_enable,
.disable = nf_defrag_ipv4_disable,
};
@@ -98,6 +98,7 @@ static void __net_exit defrag6_net_exit(struct net *net)
}
static const struct nf_defrag_v6_hook defrag_hook = {
+ .owner = THIS_MODULE,
.enable = nf_defrag_ipv6_enable,
.disable = nf_defrag_ipv6_disable,
};
@@ -2,6 +2,7 @@
#include <linux/bpf.h>
#include <linux/filter.h>
#include <linux/kmod.h>
+#include <linux/module.h>
#include <linux/netfilter.h>
#include <net/netfilter/nf_bpf_link.h>
@@ -53,7 +54,15 @@ static int bpf_nf_enable_defrag(struct bpf_nf_link *link)
}
}
+ /* Prevent defrag module from going away while in use */
+ if (!try_module_get(v4_hook->owner)) {
+ err = -ENOENT;
+ goto out_v4;
+ }
+
err = v4_hook->enable(link->net);
+ if (err)
+ module_put(v4_hook->owner);
out_v4:
rcu_read_unlock();
return err;
@@ -77,7 +86,15 @@ static int bpf_nf_enable_defrag(struct bpf_nf_link *link)
}
}
+ /* Prevent defrag module from going away while in use */
+ if (!try_module_get(v6_hook->owner)) {
+ err = -ENOENT;
+ goto out_v6;
+ }
+
err = v6_hook->enable(link->net);
+ if (err)
+ module_put(v6_hook->owner);
out_v6:
rcu_read_unlock();
return err;
@@ -97,8 +114,10 @@ static void bpf_nf_disable_defrag(struct bpf_nf_link *link)
case NFPROTO_IPV4:
rcu_read_lock();
v4_hook = rcu_dereference(nf_defrag_v4_hook);
- if (v4_hook)
+ if (v4_hook) {
v4_hook->disable(link->net);
+ module_put(v4_hook->owner);
+ }
rcu_read_unlock();
break;
@@ -107,8 +126,10 @@ static void bpf_nf_disable_defrag(struct bpf_nf_link *link)
case NFPROTO_IPV6:
rcu_read_lock();
v6_hook = rcu_dereference(nf_defrag_v6_hook);
- if (v6_hook)
+ if (v6_hook) {
v6_hook->disable(link->net);
+ module_put(v6_hook->owner);
+ }
rcu_read_unlock();
break;