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

Luis Henriques luis.henriques at canonical.com
Wed Feb 5 13:16: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.11.y-queue branch of the 3.11.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.11.y-queue

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.11.y.z tree, see
https://wiki.ubuntu.com/Kernel/Dev/ExtendedStable

Thanks.
-Luis

------

>From 17c1ea5517533f6efde0ebe1f48fd1bf5ab7d7b3 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: Luis Henriques <luis.henriques 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 a51ad07..bbe1402 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -1601,6 +1601,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,
@@ -1612,6 +1621,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