tun: Grab the netns in open.
Grabbing namespaces in open, and putting them in close always seems to
be the cleanest approach with the fewest surprises.
So now that we have tun_file so we have somepleace to put the network
namespace, let's grab the network namespace on file open and put on
file close.
Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index d3a665d..dfbf586 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -89,6 +89,7 @@
struct tun_file {
struct tun_struct *tun;
+ struct net *net;
};
struct tun_struct {
@@ -131,7 +132,6 @@
tfile->tun = tun;
tun->tfile = tfile;
- get_net(dev_net(tun->dev));
return 0;
}
@@ -143,7 +143,6 @@
/* Detach from net device */
tfile->tun = NULL;
tun->tfile = NULL;
- put_net(dev_net(tun->dev));
/* Drop read queue */
skb_queue_purge(&tun->readq);
@@ -936,6 +935,7 @@
static int tun_chr_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
+ struct tun_file *tfile = file->private_data;
struct tun_struct *tun;
void __user* argp = (void __user*)arg;
struct ifreq ifr;
@@ -954,14 +954,14 @@
(unsigned int __user*)argp);
}
- tun = tun_get(file);
+ tun = __tun_get(tfile);
if (cmd == TUNSETIFF && !tun) {
int err;
ifr.ifr_name[IFNAMSIZ-1] = '\0';
rtnl_lock();
- err = tun_set_iff(current->nsproxy->net_ns, file, &ifr);
+ err = tun_set_iff(tfile->net, file, &ifr);
rtnl_unlock();
if (err)
@@ -1125,6 +1125,7 @@
if (!tfile)
return -ENOMEM;
tfile->tun = NULL;
+ tfile->net = get_net(current->nsproxy->net_ns);
file->private_data = tfile;
return 0;
}
@@ -1148,6 +1149,7 @@
rtnl_unlock();
}
+ put_net(tfile->net);
kfree(tfile);
return 0;