| From c2892f02712e9516d72841d5c019ed6916329794 Mon Sep 17 00:00:00 2001 |
| From: Alexey Dobriyan <adobriyan@gmail.com> |
| Date: Tue, 16 Feb 2010 07:57:44 +0000 |
| Subject: gre: fix netns vs proto registration ordering |
| |
| From: Alexey Dobriyan <adobriyan@gmail.com> |
| |
| 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> |
| |
| --- |
| net/ipv4/ip_gre.c | 19 ++++++++++--------- |
| 1 file changed, 10 insertions(+), 9 deletions(-) |
| |
| --- 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); |