Skip to content

Commit

Permalink
net: Add module reference to FIB notifiers
Browse files Browse the repository at this point in the history
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: 04b1d4e ("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>
  • Loading branch information
Ido Schimmel authored and David S. Miller committed Sep 2, 2017
1 parent 9e2cf36 commit 864150d
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 2 deletions.
2 changes: 2 additions & 0 deletions include/net/fib_notifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand All @@ -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;
};

Expand Down
13 changes: 11 additions & 2 deletions net/core/fib_notifier.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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();

Expand All @@ -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;
}
Expand Down
2 changes: 2 additions & 0 deletions net/ipv4/fib_notifier.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions net/ipv6/fib6_notifier.c
Original file line number Diff line number Diff line change
@@ -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>
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 864150d

Please sign in to comment.