summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Dobriyan <adobriyan@gmail.com>2010-02-16 07:57:44 +0000
committerDavid S. Miller <davem@davemloft.net>2010-02-16 14:55:21 -0800
commitc2892f02712e9516d72841d5c019ed6916329794 (patch)
treef6da925f46344ea4f1e3a7887aca4e62be6ea3ff
parent749f621e20ab0db35a15ff730088922603c809ba (diff)
downloadlinux-c2892f02712e9516d72841d5c019ed6916329794.tar.bz2
gre: fix netns vs proto registration ordering
GRE protocol receive hook can be called right after protocol addition is done. If netns stuff is not yet initialized, we're going to oops in net_generic(). This is remotely oopsable if ip_gre is compiled as module and packet comes at unfortunate moment of module loading. Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ipv4/ip_gre.c19
1 files changed, 10 insertions, 9 deletions
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 7631b20490f5..a2a5983dbf03 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -1665,14 +1665,15 @@ static int __init ipgre_init(void)
printk(KERN_INFO "GRE over IPv4 tunneling driver\n");
- if (inet_add_protocol(&ipgre_protocol, IPPROTO_GRE) < 0) {
- printk(KERN_INFO "ipgre init: can't add protocol\n");
- return -EAGAIN;
- }
-
err = register_pernet_device(&ipgre_net_ops);
if (err < 0)
- goto gen_device_failed;
+ return err;
+
+ err = inet_add_protocol(&ipgre_protocol, IPPROTO_GRE);
+ if (err < 0) {
+ printk(KERN_INFO "ipgre init: can't add protocol\n");
+ goto add_proto_failed;
+ }
err = rtnl_link_register(&ipgre_link_ops);
if (err < 0)
@@ -1688,9 +1689,9 @@ out:
tap_ops_failed:
rtnl_link_unregister(&ipgre_link_ops);
rtnl_link_failed:
- unregister_pernet_device(&ipgre_net_ops);
-gen_device_failed:
inet_del_protocol(&ipgre_protocol, IPPROTO_GRE);
+add_proto_failed:
+ unregister_pernet_device(&ipgre_net_ops);
goto out;
}
@@ -1698,9 +1699,9 @@ static void __exit ipgre_fini(void)
{
rtnl_link_unregister(&ipgre_tap_ops);
rtnl_link_unregister(&ipgre_link_ops);
- unregister_pernet_device(&ipgre_net_ops);
if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0)
printk(KERN_INFO "ipgre close: can't remove protocol\n");
+ unregister_pernet_device(&ipgre_net_ops);
}
module_init(ipgre_init);