Patchwork [hardy,CVE,1/1] tunnels: fix netns vs proto registration ordering

login
register
mail settings
Submitter Andy Whitcroft
Date Oct. 27, 2011, 2:08 p.m.
Message ID <1319724531-6686-2-git-send-email-apw@canonical.com>
Download mbox | patch
Permalink /patch/122162/
State New
Headers show

Comments

Andy Whitcroft - Oct. 27, 2011, 2:08 p.m.
From: Alexey Dobriyan <adobriyan@gmail.com>

Same stuff as in ip_gre patch: receive hook can be called before netns
setup is done, oopsing in net_generic().

Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

(backported from commit d5aa407f59f5b83d2c50ec88f5bf56d40f1f8978)
CVE-2011-1768
BugLink: http://bugs.launchpad.net/bugs/869215
Signed-off-by: Andy Whitcroft <apw@canonical.com>
---
 net/ipv4/ipip.c         |   18 ++++++++++--------
 net/ipv6/ip6_tunnel.c   |   33 +++++++++++++++++----------------
 net/ipv6/sit.c          |   19 ++++++++++---------
 net/ipv6/xfrm6_tunnel.c |   18 +++++++++---------
 4 files changed, 46 insertions(+), 42 deletions(-)

Patch

diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 8c2b2b0..44446fd 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -863,29 +863,31 @@  static int __init ipip_init(void)
 
 	printk(banner);
 
-	if (xfrm4_tunnel_register(&ipip_handler, AF_INET)) {
-		printk(KERN_INFO "ipip init: can't register tunnel\n");
-		return -EAGAIN;
-	}
-
 	ipip_fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel),
 					   "tunl0",
 					   ipip_tunnel_setup);
 	if (!ipip_fb_tunnel_dev) {
 		err = -ENOMEM;
-		goto err1;
+		goto out;
 	}
 
 	ipip_fb_tunnel_dev->init = ipip_fb_tunnel_init;
 
 	if ((err = register_netdev(ipip_fb_tunnel_dev)))
+		goto err1;
+
+	if (xfrm4_tunnel_register(&ipip_handler, AF_INET)) {
+		printk(KERN_INFO "ipip init: can't register tunnel\n");
+		err = -EAGAIN;
 		goto err2;
+	}
+
  out:
 	return err;
  err2:
-	free_netdev(ipip_fb_tunnel_dev);
+	unregister_netdev(ipip_fb_tunnel_dev);
  err1:
-	xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
+	free_netdev(ipip_fb_tunnel_dev);
 	goto out;
 }
 
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 81941a1..c4e3dd0 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1396,10 +1396,22 @@  static int __init ip6_tunnel_init(void)
 {
 	int  err;
 
+	ip6_fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6tnl0",
+				      ip6_tnl_dev_setup);
+	if (!ip6_fb_tnl_dev) {
+		err = -ENOMEM;
+		goto out;
+	}
+	ip6_fb_tnl_dev->init = ip6_fb_tnl_dev_init;
+
+	if ((err = register_netdev(ip6_fb_tnl_dev))) {
+		goto free_netdev;
+	}
+
 	if (xfrm6_tunnel_register(&ip4ip6_handler, AF_INET)) {
 		printk(KERN_ERR "ip6_tunnel init: can't register ip4ip6\n");
 		err = -EAGAIN;
-		goto out;
+		goto unreg_netdev;
 	}
 
 	if (xfrm6_tunnel_register(&ip6ip6_handler, AF_INET6)) {
@@ -1407,24 +1419,13 @@  static int __init ip6_tunnel_init(void)
 		err = -EAGAIN;
 		goto unreg_ip4ip6;
 	}
-	ip6_fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6tnl0",
-				      ip6_tnl_dev_setup);
-
-	if (!ip6_fb_tnl_dev) {
-		err = -ENOMEM;
-		goto fail;
-	}
-	ip6_fb_tnl_dev->init = ip6_fb_tnl_dev_init;
-
-	if ((err = register_netdev(ip6_fb_tnl_dev))) {
-		free_netdev(ip6_fb_tnl_dev);
-		goto fail;
-	}
 	return 0;
-fail:
-	xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6);
 unreg_ip4ip6:
 	xfrm6_tunnel_deregister(&ip4ip6_handler, AF_INET);
+unreg_netdev:
+	unregister_netdev(ip6_fb_tnl_dev);
+free_netdev:
+	free_netdev(ip6_fb_tnl_dev);
 out:
 	return err;
 }
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index bd22f64..3e2ce4a 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -827,29 +827,30 @@  static int __init sit_init(void)
 
 	printk(KERN_INFO "IPv6 over IPv4 tunneling driver\n");
 
-	if (xfrm4_tunnel_register(&sit_handler, AF_INET6) < 0) {
-		printk(KERN_INFO "sit init: Can't add protocol\n");
-		return -EAGAIN;
-	}
-
 	ipip6_fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "sit0",
 					   ipip6_tunnel_setup);
 	if (!ipip6_fb_tunnel_dev) {
 		err = -ENOMEM;
-		goto err1;
+		goto out;
 	}
 
 	ipip6_fb_tunnel_dev->init = ipip6_fb_tunnel_init;
 
-	if ((err =  register_netdev(ipip6_fb_tunnel_dev)))
+	if ((err = register_netdev(ipip6_fb_tunnel_dev)))
+		goto err1;
+
+	if (xfrm4_tunnel_register(&sit_handler, AF_INET6) < 0) {
+		printk(KERN_INFO "sit init: Can't add protocol\n");
+		err = -EAGAIN;
 		goto err2;
+	}
 
  out:
 	return err;
  err2:
-	free_netdev(ipip6_fb_tunnel_dev);
+	unregister_netdev(ipip6_fb_tunnel_dev);
  err1:
-	xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
+	free_netdev(ipip6_fb_tunnel_dev);
 	goto out;
 }
 
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index fae90ff..556491b 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -343,22 +343,22 @@  static struct xfrm6_tunnel xfrm46_tunnel_handler = {
 
 static int __init xfrm6_tunnel_init(void)
 {
-	if (xfrm_register_type(&xfrm6_tunnel_type, AF_INET6) < 0)
+	if (xfrm6_tunnel_spi_init() < 0)
 		return -EAGAIN;
-
-	if (xfrm6_tunnel_register(&xfrm6_tunnel_handler, AF_INET6)) {
-		xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
+		
+	if (xfrm_register_type(&xfrm6_tunnel_type, AF_INET6) < 0) {
+		xfrm6_tunnel_spi_fini();
 		return -EAGAIN;
 	}
-	if (xfrm6_tunnel_register(&xfrm46_tunnel_handler, AF_INET)) {
-		xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6);
+	if (xfrm6_tunnel_register(&xfrm6_tunnel_handler, AF_INET6)) {
 		xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
+		xfrm6_tunnel_spi_fini();
 		return -EAGAIN;
 	}
-	if (xfrm6_tunnel_spi_init() < 0) {
-		xfrm6_tunnel_deregister(&xfrm46_tunnel_handler, AF_INET);
+	if (xfrm6_tunnel_register(&xfrm46_tunnel_handler, AF_INET)) {
 		xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6);
 		xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
+		xfrm6_tunnel_spi_fini();
 		return -EAGAIN;
 	}
 	return 0;
@@ -366,10 +366,10 @@  static int __init xfrm6_tunnel_init(void)
 
 static void __exit xfrm6_tunnel_fini(void)
 {
-	xfrm6_tunnel_spi_fini();
 	xfrm6_tunnel_deregister(&xfrm46_tunnel_handler, AF_INET);
 	xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6);
 	xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
+	xfrm6_tunnel_spi_fini();
 }
 
 module_init(xfrm6_tunnel_init);