]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
gre: fix netns vs proto registration ordering
authorAlexey Dobriyan <adobriyan@gmail.com>
Tue, 16 Feb 2010 07:57:44 +0000 (07:57 +0000)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 8 Aug 2011 17:36:07 +0000 (10:36 -0700)
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>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
net/ipv4/ip_gre.c

index aa70db1ccce54de81ebfc98635408ab1a58d3fa6..f8b72dbf85f54ade4298de53ec8a1e2cdbe823c6 100644 (file)
@@ -1667,14 +1667,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)
@@ -1690,9 +1691,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;
 }
 
@@ -1700,9 +1701,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);