summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2017-09-26 19:52:58 +0200
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2017-09-26 19:52:58 +0200
commita8d545d85e8aeaa420051a7c1d504a72d455e077 (patch)
tree326e0c6253133bc72c46c7a156d24e6ea00a7143
parenta4212bf911026740afc7fce98d9100e2ef5dcea0 (diff)
netfilter: ipset: pernet ops must be unregistered last
Removing the ipset module leaves a small window where one cpu performs module removal while another runs a command like 'ipset flush'. ipset uses net_generic(), unregistering the pernet ops frees this storage area. Fix it by first removing the user-visible api handlers and the pernet ops last. Fixes: 1785e8f473082 ("netfiler: ipset: Add net namespace for ipset") Reported-by: Li Shuang <shuali@redhat.com> Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
-rw-r--r--kernel/net/netfilter/ipset/ip_set_core.c43
1 files changed, 26 insertions, 17 deletions
diff --git a/kernel/net/netfilter/ipset/ip_set_core.c b/kernel/net/netfilter/ipset/ip_set_core.c
index 4bea0b3..5ff727a 100644
--- a/kernel/net/netfilter/ipset/ip_set_core.c
+++ b/kernel/net/netfilter/ipset/ip_set_core.c
@@ -2126,32 +2126,44 @@ static struct pernet_operations ip_set_net_ops = {
#endif
};
+#ifdef HAVE_NET_OPS_ID
+#define REGISTER_PERNET_SUBSYS(s) \
+ register_pernet_subsys(s)
+#define UNREGISTER_PERNET_SUBSYS(s) \
+ unregister_pernet_subsys(s);
+#else
+#define REGISTER_PERNET_SUBSYS(s) \
+ register_pernet_gen_device(&ip_set_net_id, s)
+#define UNREGISTER_PERNET_SUBSYS(s) \
+ unregister_pernet_gen_device(ip_set_net_id, s);
+#endif
+
+
static int __init
ip_set_init(void)
{
- int ret = nfnetlink_subsys_register(&ip_set_netlink_subsys);
+ int ret = REGISTER_PERNET_SUBSYS(&ip_set_net_ops);
+
+ if (ret) {
+ pr_err("ip_set: cannot register pernet_subsys.\n");
+ return ret;
+ }
+ ret = nfnetlink_subsys_register(&ip_set_netlink_subsys);
if (ret != 0) {
pr_err("ip_set: cannot register with nfnetlink.\n");
+ UNREGISTER_PERNET_SUBSYS(&ip_set_net_ops);
return ret;
}
+
ret = nf_register_sockopt(&so_set);
if (ret != 0) {
pr_err("SO_SET registry failed: %d\n", ret);
nfnetlink_subsys_unregister(&ip_set_netlink_subsys);
+ UNREGISTER_PERNET_SUBSYS(&ip_set_net_ops);
return ret;
}
-#ifdef HAVE_NET_OPS_ID
- ret = register_pernet_subsys(&ip_set_net_ops);
-#else
- ret = register_pernet_gen_device(&ip_set_net_id, &ip_set_net_ops);
-#endif
- if (ret) {
- pr_err("ip_set: cannot register pernet_subsys.\n");
- nf_unregister_sockopt(&so_set);
- nfnetlink_subsys_unregister(&ip_set_netlink_subsys);
- return ret;
- }
+
pr_info("ip_set: protocol %u\n", IPSET_PROTOCOL);
return 0;
}
@@ -2159,13 +2171,10 @@ ip_set_init(void)
static void __exit
ip_set_fini(void)
{
-#ifdef HAVE_NET_OPS_ID
- unregister_pernet_subsys(&ip_set_net_ops);
-#else
- unregister_pernet_gen_device(ip_set_net_id, &ip_set_net_ops);
-#endif
nf_unregister_sockopt(&so_set);
nfnetlink_subsys_unregister(&ip_set_netlink_subsys);
+
+ UNREGISTER_PERNET_SUBSYS(&ip_set_net_ops);
pr_debug("these are the famous last words\n");
}