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>
This commit is contained in:
committed by
David S. Miller
parent
7c0c3b1a8a
commit
dd38bd8530
@@ -428,8 +428,10 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
|
|||||||
/* Drop read queue */
|
/* Drop read queue */
|
||||||
skb_queue_purge(&tfile->sk.sk_receive_queue);
|
skb_queue_purge(&tfile->sk.sk_receive_queue);
|
||||||
tun_set_real_num_queues(tun);
|
tun_set_real_num_queues(tun);
|
||||||
} else if (tfile->detached && clean)
|
} else if (tfile->detached && clean) {
|
||||||
tun = tun_enable_queue(tfile);
|
tun = tun_enable_queue(tfile);
|
||||||
|
sock_put(&tfile->sk);
|
||||||
|
}
|
||||||
|
|
||||||
if (clean) {
|
if (clean) {
|
||||||
if (tun && tun->numqueues == 0 && tun->numdisabled == 0 &&
|
if (tun && tun->numqueues == 0 && tun->numdisabled == 0 &&
|
||||||
@@ -478,6 +480,9 @@ static void tun_detach_all(struct net_device *dev)
|
|||||||
sock_put(&tfile->sk);
|
sock_put(&tfile->sk);
|
||||||
}
|
}
|
||||||
BUG_ON(tun->numdisabled != 0);
|
BUG_ON(tun->numdisabled != 0);
|
||||||
|
|
||||||
|
if (tun->flags & TUN_PERSIST)
|
||||||
|
module_put(THIS_MODULE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tun_attach(struct tun_struct *tun, struct file *file)
|
static 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,
|
|||||||
/* Disable/Enable persist mode. Keep an extra reference to the
|
/* Disable/Enable persist mode. Keep an extra reference to the
|
||||||
* module to prevent the module being unprobed.
|
* module to prevent the module being unprobed.
|
||||||
*/
|
*/
|
||||||
if (arg) {
|
if (arg && !(tun->flags & TUN_PERSIST)) {
|
||||||
tun->flags |= TUN_PERSIST;
|
tun->flags |= TUN_PERSIST;
|
||||||
__module_get(THIS_MODULE);
|
__module_get(THIS_MODULE);
|
||||||
} else {
|
}
|
||||||
|
if (!arg && (tun->flags & TUN_PERSIST)) {
|
||||||
tun->flags &= ~TUN_PERSIST;
|
tun->flags &= ~TUN_PERSIST;
|
||||||
module_put(THIS_MODULE);
|
module_put(THIS_MODULE);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user