aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNikolay Aleksandrov <nikolay@cumulusnetworks.com>2015-11-24 17:09:30 +0100
committerDavid S. Miller <davem@davemloft.net>2015-11-24 17:15:56 -0500
commitfbdd29bfd2da979b7ac6a0084af56624156c1069 (patch)
treec019c641c0c6130a769a596561529253e49bec13
parentrxrpc: Correctly handle ack at end of client call transmit phase (diff)
downloadlinux-dev-fbdd29bfd2da979b7ac6a0084af56624156c1069.tar.xz
linux-dev-fbdd29bfd2da979b7ac6a0084af56624156c1069.zip
net: ipmr, ip6mr: fix vif/tunnel failure race condition
Since (at least) commit b17a7c179dd3 ("[NET]: Do sysfs registration as part of register_netdevice."), netdev_run_todo() deals only with unregistration, so we don't need to do the rtnl_unlock/lock cycle to finish registration when failing pimreg or dvmrp device creation. In fact that opens a race condition where someone can delete the device while rtnl is unlocked because it's fully registered. The problem gets worse when netlink support is introduced as there are more points of entry that can cause it and it also makes reusing that code correctly impossible. Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> Reviewed-by: Cong Wang <cwang@twopensource.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ipv4/ipmr.c8
-rw-r--r--net/ipv6/ip6mr.c4
2 files changed, 0 insertions, 12 deletions
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 292123bc30fa..c3a38353f5dc 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -441,10 +441,6 @@ struct net_device *ipmr_new_tunnel(struct net *net, struct vifctl *v)
return dev;
failure:
- /* allow the register to be completed before unregistering. */
- rtnl_unlock();
- rtnl_lock();
-
unregister_netdevice(dev);
return NULL;
}
@@ -540,10 +536,6 @@ static struct net_device *ipmr_reg_vif(struct net *net, struct mr_table *mrt)
return dev;
failure:
- /* allow the register to be completed before unregistering. */
- rtnl_unlock();
- rtnl_lock();
-
unregister_netdevice(dev);
return NULL;
}
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 7a4a1b81dbb6..a10e77103c88 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -765,10 +765,6 @@ static struct net_device *ip6mr_reg_vif(struct net *net, struct mr6_table *mrt)
return dev;
failure:
- /* allow the register to be completed before unregistering. */
- rtnl_unlock();
- rtnl_lock();
-
unregister_netdevice(dev);
return NULL;
}