提交 dd38bd85 编写于 作者: J Jason Wang 提交者: David S. Miller

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: NJason Wang <jasowang@redhat.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 7c0c3b1a
...@@ -428,8 +428,10 @@ static void __tun_detach(struct tun_file *tfile, bool clean) ...@@ -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) ...@@ -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, ...@@ -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);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册