aboutsummaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorAlexey Dobriyan <adobriyan@gmail.com>2010-02-16 07:57:44 +0000
committerGreg Kroah-Hartman <gregkh@suse.de>2011-08-08 10:23:17 -0700
commit7606088a8d06062750d6d24cab6e064d7711356e (patch)
tree67f2d3bf3bd8fbcd7c0b3d415473f9dad6f08d84 /net
parent39371f2a8a7c27a63882c1586c3ee72f05eb6527 (diff)
gre: fix netns vs proto registration ordering
commit c2892f02712e9516d72841d5c019ed6916329794 upstream. 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> [dannf: backported to Debian's 2.6.32] Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to '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 cfab9e419ef..f6145847186 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_gen_device(&ipgre_net_id, &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_gen_device(ipgre_net_id, &ipgre_net_ops);
-gen_device_failed:
inet_del_protocol(&ipgre_protocol, IPPROTO_GRE);
+add_proto_failed:
+ unregister_pernet_gen_device(ipgre_net_id, &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_gen_device(ipgre_net_id, &ipgre_net_ops);
if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0)
printk(KERN_INFO "ipgre close: can't remove protocol\n");
+ unregister_pernet_gen_device(ipgre_net_id, &ipgre_net_ops);
}
module_init(ipgre_init);