aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/tun.c32
1 files changed, 19 insertions, 13 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 16716aef184c..95ae40ab8718 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -156,6 +156,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file)
156 tfile->tun = tun; 156 tfile->tun = tun;
157 tun->tfile = tfile; 157 tun->tfile = tfile;
158 dev_hold(tun->dev); 158 dev_hold(tun->dev);
159 sock_hold(tun->sk);
159 atomic_inc(&tfile->count); 160 atomic_inc(&tfile->count);
160 161
161out: 162out:
@@ -165,11 +166,8 @@ out:
165 166
166static void __tun_detach(struct tun_struct *tun) 167static void __tun_detach(struct tun_struct *tun)
167{ 168{
168 struct tun_file *tfile = tun->tfile;
169
170 /* Detach from net device */ 169 /* Detach from net device */
171 netif_tx_lock_bh(tun->dev); 170 netif_tx_lock_bh(tun->dev);
172 tfile->tun = NULL;
173 tun->tfile = NULL; 171 tun->tfile = NULL;
174 netif_tx_unlock_bh(tun->dev); 172 netif_tx_unlock_bh(tun->dev);
175 173
@@ -339,6 +337,13 @@ static void tun_net_uninit(struct net_device *dev)
339 } 337 }
340} 338}
341 339
340static void tun_free_netdev(struct net_device *dev)
341{
342 struct tun_struct *tun = netdev_priv(dev);
343
344 sock_put(tun->sk);
345}
346
342/* Net device open. */ 347/* Net device open. */
343static int tun_net_open(struct net_device *dev) 348static int tun_net_open(struct net_device *dev)
344{ 349{
@@ -811,7 +816,7 @@ static void tun_setup(struct net_device *dev)
811 tun->group = -1; 816 tun->group = -1;
812 817
813 dev->ethtool_ops = &tun_ethtool_ops; 818 dev->ethtool_ops = &tun_ethtool_ops;
814 dev->destructor = free_netdev; 819 dev->destructor = tun_free_netdev;
815} 820}
816 821
817/* Trivial set of netlink ops to allow deleting tun or tap 822/* Trivial set of netlink ops to allow deleting tun or tap
@@ -848,7 +853,7 @@ static void tun_sock_write_space(struct sock *sk)
848 853
849static void tun_sock_destruct(struct sock *sk) 854static void tun_sock_destruct(struct sock *sk)
850{ 855{
851 dev_put(container_of(sk, struct tun_sock, sk)->tun->dev); 856 free_netdev(container_of(sk, struct tun_sock, sk)->tun->dev);
852} 857}
853 858
854static struct proto tun_proto = { 859static struct proto tun_proto = {
@@ -920,11 +925,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
920 if (!sk) 925 if (!sk)
921 goto err_free_dev; 926 goto err_free_dev;
922 927
923 /* This ref count is for tun->sk. */
924 dev_hold(dev);
925 sock_init_data(&tun->socket, sk); 928 sock_init_data(&tun->socket, sk);
926 sk->sk_write_space = tun_sock_write_space; 929 sk->sk_write_space = tun_sock_write_space;
927 sk->sk_destruct = tun_sock_destruct;
928 sk->sk_sndbuf = INT_MAX; 930 sk->sk_sndbuf = INT_MAX;
929 sk->sk_sleep = &tfile->read_wait; 931 sk->sk_sleep = &tfile->read_wait;
930 932
@@ -942,11 +944,13 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
942 err = -EINVAL; 944 err = -EINVAL;
943 err = register_netdevice(tun->dev); 945 err = register_netdevice(tun->dev);
944 if (err < 0) 946 if (err < 0)
945 goto err_free_dev; 947 goto err_free_sk;
948
949 sk->sk_destruct = tun_sock_destruct;
946 950
947 err = tun_attach(tun, file); 951 err = tun_attach(tun, file);
948 if (err < 0) 952 if (err < 0)
949 goto err_free_dev; 953 goto failed;
950 } 954 }
951 955
952 DBG(KERN_INFO "%s: tun_set_iff\n", tun->dev->name); 956 DBG(KERN_INFO "%s: tun_set_iff\n", tun->dev->name);
@@ -1284,14 +1288,16 @@ static int tun_chr_close(struct inode *inode, struct file *file)
1284 __tun_detach(tun); 1288 __tun_detach(tun);
1285 1289
1286 /* If desireable, unregister the netdevice. */ 1290 /* If desireable, unregister the netdevice. */
1287 if (!(tun->flags & TUN_PERSIST)) { 1291 if (!(tun->flags & TUN_PERSIST))
1288 sock_put(tun->sk);
1289 unregister_netdevice(tun->dev); 1292 unregister_netdevice(tun->dev);
1290 }
1291 1293
1292 rtnl_unlock(); 1294 rtnl_unlock();
1293 } 1295 }
1294 1296
1297 tun = tfile->tun;
1298 if (tun)
1299 sock_put(tun->sk);
1300
1295 put_net(tfile->net); 1301 put_net(tfile->net);
1296 kfree(tfile); 1302 kfree(tfile);
1297 1303