aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2012-08-22 17:50:59 -0400
committerDavid S. Miller <davem@davemloft.net>2012-08-23 12:24:42 -0400
commit748e2d9396a18c3fd3d07d47c1b41320acf1fbf4 (patch)
tree49bde8c370615258baada1d43acda2b3fb3625c2 /net/core
parent0fa7fa98dbcc2789409ed24e885485e645803d7f (diff)
net: reinstate rtnl in call_netdevice_notifiers()
Eric Biederman pointed out that not holding RTNL while calling call_netdevice_notifiers() was racy. This patch is a direct transcription his feedback against commit 0115e8e30d6fc (net: remove delay at device dismantle) Thanks Eric ! Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Tom Herbert <therbert@google.com> Cc: Mahesh Bandewar <maheshb@google.com> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Gao feng <gaofeng@cn.fujitsu.com> Acked-by: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/dev.c9
-rw-r--r--net/core/fib_rules.c3
2 files changed, 8 insertions, 4 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 0640d2a859c6..bc857fead8c8 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1466,8 +1466,7 @@ EXPORT_SYMBOL(unregister_netdevice_notifier);
1466 1466
1467int call_netdevice_notifiers(unsigned long val, struct net_device *dev) 1467int call_netdevice_notifiers(unsigned long val, struct net_device *dev)
1468{ 1468{
1469 if (val != NETDEV_UNREGISTER_FINAL) 1469 ASSERT_RTNL();
1470 ASSERT_RTNL();
1471 return raw_notifier_call_chain(&netdev_chain, val, dev); 1470 return raw_notifier_call_chain(&netdev_chain, val, dev);
1472} 1471}
1473EXPORT_SYMBOL(call_netdevice_notifiers); 1472EXPORT_SYMBOL(call_netdevice_notifiers);
@@ -5782,7 +5781,11 @@ static void netdev_wait_allrefs(struct net_device *dev)
5782 5781
5783 /* Rebroadcast unregister notification */ 5782 /* Rebroadcast unregister notification */
5784 call_netdevice_notifiers(NETDEV_UNREGISTER, dev); 5783 call_netdevice_notifiers(NETDEV_UNREGISTER, dev);
5784
5785 __rtnl_unlock();
5785 rcu_barrier(); 5786 rcu_barrier();
5787 rtnl_lock();
5788
5786 call_netdevice_notifiers(NETDEV_UNREGISTER_FINAL, dev); 5789 call_netdevice_notifiers(NETDEV_UNREGISTER_FINAL, dev);
5787 if (test_bit(__LINK_STATE_LINKWATCH_PENDING, 5790 if (test_bit(__LINK_STATE_LINKWATCH_PENDING,
5788 &dev->state)) { 5791 &dev->state)) {
@@ -5855,7 +5858,9 @@ void netdev_run_todo(void)
5855 = list_first_entry(&list, struct net_device, todo_list); 5858 = list_first_entry(&list, struct net_device, todo_list);
5856 list_del(&dev->todo_list); 5859 list_del(&dev->todo_list);
5857 5860
5861 rtnl_lock();
5858 call_netdevice_notifiers(NETDEV_UNREGISTER_FINAL, dev); 5862 call_netdevice_notifiers(NETDEV_UNREGISTER_FINAL, dev);
5863 __rtnl_unlock();
5859 5864
5860 if (unlikely(dev->reg_state != NETREG_UNREGISTERING)) { 5865 if (unlikely(dev->reg_state != NETREG_UNREGISTERING)) {
5861 pr_err("network todo '%s' but state %d\n", 5866 pr_err("network todo '%s' but state %d\n",
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 585093755c23..ab7db83236c9 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -711,16 +711,15 @@ static int fib_rules_event(struct notifier_block *this, unsigned long event,
711 struct net *net = dev_net(dev); 711 struct net *net = dev_net(dev);
712 struct fib_rules_ops *ops; 712 struct fib_rules_ops *ops;
713 713
714 ASSERT_RTNL();
714 715
715 switch (event) { 716 switch (event) {
716 case NETDEV_REGISTER: 717 case NETDEV_REGISTER:
717 ASSERT_RTNL();
718 list_for_each_entry(ops, &net->rules_ops, list) 718 list_for_each_entry(ops, &net->rules_ops, list)
719 attach_rules(&ops->rules_list, dev); 719 attach_rules(&ops->rules_list, dev);
720 break; 720 break;
721 721
722 case NETDEV_UNREGISTER: 722 case NETDEV_UNREGISTER:
723 ASSERT_RTNL();
724 list_for_each_entry(ops, &net->rules_ops, list) 723 list_for_each_entry(ops, &net->rules_ops, list)
725 detach_rules(&ops->rules_list, dev); 724 detach_rules(&ops->rules_list, dev);
726 break; 725 break;