net: Add module reference to FIB notifiers
authorIdo Schimmel <idosch@mellanox.com>
Fri, 1 Sep 2017 09:15:17 +0000 (12:15 +0300)
committerDavid S. Miller <davem@davemloft.net>
Sat, 2 Sep 2017 03:33:42 +0000 (20:33 -0700)
When a listener registers to the FIB notification chain it receives a
dump of the FIB entries and rules from existing address families by
invoking their dump operations.

While we call into these modules we need to make sure they aren't
removed. Do that by increasing their reference count before invoking
their dump operations and decrease it afterwards.

Fixes: 04b1d4e50e82 ("net: core: Make the FIB notification chain generic")
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/fib_notifier.h
net/core/fib_notifier.c
net/ipv4/fib_notifier.c
net/ipv6/fib6_notifier.c

index 241475224f74c4bc44dd05ebe03783da90e70f56..669b9716dc7a67c8c9048d70a97229546d8fc29b 100644 (file)
@@ -2,6 +2,7 @@
 #define __NET_FIB_NOTIFIER_H
 
 #include <linux/types.h>
+#include <linux/module.h>
 #include <linux/notifier.h>
 #include <net/net_namespace.h>
 
@@ -26,6 +27,7 @@ struct fib_notifier_ops {
        struct list_head list;
        unsigned int (*fib_seq_read)(struct net *net);
        int (*fib_dump)(struct net *net, struct notifier_block *nb);
+       struct module *owner;
        struct rcu_head rcu;
 };
 
index 292aab83702f69ab5557f1f8ce3c93f7f108f5fb..4fc202dbdfb607c6042c2de12b71b4a3b1fa2fef 100644 (file)
@@ -2,6 +2,7 @@
 #include <linux/notifier.h>
 #include <linux/rcupdate.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/init.h>
 #include <net/net_namespace.h>
 #include <net/fib_notifier.h>
@@ -33,8 +34,12 @@ static unsigned int fib_seq_sum(void)
 
        rtnl_lock();
        for_each_net(net) {
-               list_for_each_entry(ops, &net->fib_notifier_ops, list)
+               list_for_each_entry(ops, &net->fib_notifier_ops, list) {
+                       if (!try_module_get(ops->owner))
+                               continue;
                        fib_seq += ops->fib_seq_read(net);
+                       module_put(ops->owner);
+               }
        }
        rtnl_unlock();
 
@@ -46,8 +51,12 @@ static int fib_net_dump(struct net *net, struct notifier_block *nb)
        struct fib_notifier_ops *ops;
 
        list_for_each_entry_rcu(ops, &net->fib_notifier_ops, list) {
-               int err = ops->fib_dump(net, nb);
+               int err;
 
+               if (!try_module_get(ops->owner))
+                       continue;
+               err = ops->fib_dump(net, nb);
+               module_put(ops->owner);
                if (err)
                        return err;
        }
index 5d7afb14556231ed930de3996a549e7e5556a42d..cfd420b0572c98cb99dc9217b668f01be3050acd 100644 (file)
@@ -2,6 +2,7 @@
 #include <linux/notifier.h>
 #include <linux/socket.h>
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <net/net_namespace.h>
 #include <net/fib_notifier.h>
 #include <net/netns/ipv4.h>
@@ -49,6 +50,7 @@ static const struct fib_notifier_ops fib4_notifier_ops_template = {
        .family         = AF_INET,
        .fib_seq_read   = fib4_seq_read,
        .fib_dump       = fib4_dump,
+       .owner          = THIS_MODULE,
 };
 
 int __net_init fib4_notifier_init(struct net *net)
index 66a103ef7e864a917a899cea4981efc87d26a7e4..05f82baaa99ef13dcd419b91fd4460eba54a6ab6 100644 (file)
@@ -1,6 +1,7 @@
 #include <linux/notifier.h>
 #include <linux/socket.h>
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <net/net_namespace.h>
 #include <net/fib_notifier.h>
 #include <net/netns/ipv6.h>
@@ -41,6 +42,7 @@ static const struct fib_notifier_ops fib6_notifier_ops_template = {
        .family         = AF_INET6,
        .fib_seq_read   = fib6_seq_read,
        .fib_dump       = fib6_dump,
+       .owner          = THIS_MODULE,
 };
 
 int __net_init fib6_notifier_init(struct net *net)