[3.8.y.z extended stable] Patch "sit: fix double free of fb_tunnel_dev on exit" has been added to staging queue

Kamal Mostafa kamal at canonical.com
Mon Feb 10 19:25:41 UTC 2014


This is a note to let you know that I have just added a patch titled

    sit: fix double free of fb_tunnel_dev on exit

to the linux-3.8.y-queue branch of the 3.8.y.z extended stable tree 
which can be found at:

 http://kernel.ubuntu.com/git?p=ubuntu/linux.git;a=shortlog;h=refs/heads/linux-3.8.y-queue

This patch is scheduled to be released in version 3.8.13.18.

If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 3.8.y.z tree, see
https://wiki.ubuntu.com/Kernel/Dev/ExtendedStable

Thanks.
-Kamal

------

>From 0acb431da543e240588d58086db374ca89c7c387 Mon Sep 17 00:00:00 2001
From: Nicolas Dichtel <nicolas.dichtel at 6wind.com>
Date: Fri, 31 Jan 2014 09:24:04 +0100
Subject: sit: fix double free of fb_tunnel_dev on exit

[ No relevant upstream commit. ]

This problem was fixed upstream by commit 9434266f2c64 ("sit: fix use after free
of fb_tunnel_dev").
The upstream patch depends on upstream commit 5e6700b3bf98 ("sit: add support of
x-netns"), which was not backported into 3.10 branch.

First, explain the problem: when the sit module is unloaded, sit_cleanup() is
called.
rmmod sit
=> sit_cleanup()
  => rtnl_link_unregister()
    => __rtnl_kill_links()
      => for_each_netdev(net, dev) {
        if (dev->rtnl_link_ops == ops)
        	ops->dellink(dev, &list_kill);
        }
At this point, the FB device is deleted (and all sit tunnels).
  => unregister_pernet_device()
    => unregister_pernet_operations()
      => ops_exit_list()
        => sit_exit_net()
          => sit_destroy_tunnels()
          In this function, no tunnel is found.
          => unregister_netdevice_queue(sitn->fb_tunnel_dev, &list);
We delete the FB device a second time here!

Because we cannot simply remove the second deletion (sit_exit_net() must remove
the FB device when a netns is deleted), we add an rtnl ops which delete all sit
device excepting the FB device and thus we can keep the explicit deletion in
sit_exit_net().

CC: Steven Rostedt <rostedt at goodmis.org>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel at 6wind.com>
Acked-by: Willem de Bruijn <willemb at google.com>
Reported-by: Steven Rostedt <srostedt at redhat.com>
Tested-by: Steven Rostedt <srostedt at redhat.com> (and our entire MRG team)
Tested-by: "Luis Claudio R. Goncalves" <lgoncalv at redhat.com>
Tested-by: John Kacur <jkacur at redhat.com>
Signed-off-by: Kamal Mostafa <kamal at canonical.com>
---
 net/ipv6/sit.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index b1c5654..0511f0e 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -1463,6 +1463,15 @@ static const struct nla_policy ipip6_policy[IFLA_IPTUN_MAX + 1] = {
 #endif
 };

+static void ipip6_dellink(struct net_device *dev, struct list_head *head)
+{
+	struct net *net = dev_net(dev);
+	struct sit_net *sitn = net_generic(net, sit_net_id);
+
+	if (dev != sitn->fb_tunnel_dev)
+		unregister_netdevice_queue(dev, head);
+}
+
 static struct rtnl_link_ops sit_link_ops __read_mostly = {
 	.kind		= "sit",
 	.maxtype	= IFLA_IPTUN_MAX,
@@ -1473,6 +1482,7 @@ static struct rtnl_link_ops sit_link_ops __read_mostly = {
 	.changelink	= ipip6_changelink,
 	.get_size	= ipip6_get_size,
 	.fill_info	= ipip6_fill_info,
+	.dellink	= ipip6_dellink,
 };

 static struct xfrm_tunnel sit_handler __read_mostly = {
--
1.8.3.2





More information about the kernel-team mailing list