aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/tun.c
diff options
context:
space:
mode:
authorJason Wang <jasowang@redhat.com>2013-01-11 11:59:34 -0500
committerDavid S. Miller <davem@davemloft.net>2013-01-11 22:42:02 -0500
commitdd38bd853082355641d0034aaf368e13ef2438f8 (patch)
treed30449d71cc6c1cbe9d5cc412c2046f4c1527c43 /drivers/net/tun.c
parent7c0c3b1a8a175437991ccc898ed66ec5e4a96208 (diff)
tuntap: fix leaking reference count
Reference count leaking of both module and sock were found: - When a detached file were closed, its sock refcnt from device were not released, solving this by add the sock_put(). - The module were hold or drop unconditionally in TUNSETPERSIST, which means we if we set the persist flag for N times, we need unset it for another N times. Solving this by only hold or drop an reference when there's a flag change and also drop the reference count when the persist device is deleted. Signed-off-by: Jason Wang <jasowang@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/tun.c')
-rw-r--r--drivers/net/tun.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index a36b56f0940b..af372d0957fe 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -428,8 +428,10 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
428 /* Drop read queue */ 428 /* Drop read queue */
429 skb_queue_purge(&tfile->sk.sk_receive_queue); 429 skb_queue_purge(&tfile->sk.sk_receive_queue);
430 tun_set_real_num_queues(tun); 430 tun_set_real_num_queues(tun);
431 } else if (tfile->detached && clean) 431 } else if (tfile->detached && clean) {
432 tun = tun_enable_queue(tfile); 432 tun = tun_enable_queue(tfile);
433 sock_put(&tfile->sk);
434 }
433 435
434 if (clean) { 436 if (clean) {
435 if (tun && tun->numqueues == 0 && tun->numdisabled == 0 && 437 if (tun && tun->numqueues == 0 && tun->numdisabled == 0 &&
@@ -478,6 +480,9 @@ static void tun_detach_all(struct net_device *dev)
478 sock_put(&tfile->sk); 480 sock_put(&tfile->sk);
479 } 481 }
480 BUG_ON(tun->numdisabled != 0); 482 BUG_ON(tun->numdisabled != 0);
483
484 if (tun->flags & TUN_PERSIST)
485 module_put(THIS_MODULE);
481} 486}
482 487
483static int tun_attach(struct tun_struct *tun, struct file *file) 488static int tun_attach(struct tun_struct *tun, struct file *file)
@@ -1874,10 +1879,11 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
1874 /* Disable/Enable persist mode. Keep an extra reference to the 1879 /* Disable/Enable persist mode. Keep an extra reference to the
1875 * module to prevent the module being unprobed. 1880 * module to prevent the module being unprobed.
1876 */ 1881 */
1877 if (arg) { 1882 if (arg && !(tun->flags & TUN_PERSIST)) {
1878 tun->flags |= TUN_PERSIST; 1883 tun->flags |= TUN_PERSIST;
1879 __module_get(THIS_MODULE); 1884 __module_get(THIS_MODULE);
1880 } else { 1885 }
1886 if (!arg && (tun->flags & TUN_PERSIST)) {
1881 tun->flags &= ~TUN_PERSIST; 1887 tun->flags &= ~TUN_PERSIST;
1882 module_put(THIS_MODULE); 1888 module_put(THIS_MODULE);
1883 } 1889 }