summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Wang <jasowang@redhat.com>2013-09-11 18:09:48 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-10-13 16:08:29 -0700
commita81a02460bdf054ca0c60c5aed29941f7134092d (patch)
treeaaf3e865f6107a1dab96f3ad059754a9cf1e84b3
parente66bdd7106911886aebf118e1c1aebb5a26d0752 (diff)
downloadlinux-3.10-a81a02460bdf054ca0c60c5aed29941f7134092d.tar.gz
linux-3.10-a81a02460bdf054ca0c60c5aed29941f7134092d.tar.bz2
linux-3.10-a81a02460bdf054ca0c60c5aed29941f7134092d.zip
tuntap: correctly handle error in tun_set_iff()
[ Upstream commit 662ca437e714caaab855b12415d6ffd815985bc0 ] Commit c8d68e6be1c3b242f1c598595830890b65cea64a (tuntap: multiqueue support) only call free_netdev() on error in tun_set_iff(). This causes several issues: - memory of tun security were leaked - use after free since the flow gc timer was not deleted and the tfile were not detached This patch solves the above issues. Reported-by: Wannes Rombouts <wannes.rombouts@epitech.eu> Cc: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Jason Wang <jasowang@redhat.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/net/tun.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 7b54f4f052d..b18ead55699 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1693,11 +1693,11 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
INIT_LIST_HEAD(&tun->disabled);
err = tun_attach(tun, file);
if (err < 0)
- goto err_free_dev;
+ goto err_free_flow;
err = register_netdevice(tun->dev);
if (err < 0)
- goto err_free_dev;
+ goto err_detach;
if (device_create_file(&tun->dev->dev, &dev_attr_tun_flags) ||
device_create_file(&tun->dev->dev, &dev_attr_owner) ||
@@ -1741,7 +1741,12 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
strcpy(ifr->ifr_name, tun->dev->name);
return 0;
- err_free_dev:
+err_detach:
+ tun_detach_all(dev);
+err_free_flow:
+ tun_flow_uninit(tun);
+ security_tun_dev_free_security(tun->security);
+err_free_dev:
free_netdev(dev);
return err;
}