Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4df0bfc7 authored by Cong Wang's avatar Cong Wang Committed by David S. Miller
Browse files

tun: fix a memory leak for tfile->tx_array



tfile->tun could be detached before we close the tun fd,
via tun_detach_all(), so it should not be used to check for
tfile->tx_array.

As Jason suggested, we probably have to clean it up
unconditionally both in __tun_deatch() and tun_detach_all(),
but this requires to check if it is initialized or not.
Currently skb_array_cleanup() doesn't have such a check,
so I check it in the caller and introduce a helper function,
it is a bit ugly but we can always improve it in net-next.

Reported-by: default avatarDmitry Vyukov <dvyukov@google.com>
Fixes: 1576d986 ("tun: switch to use skb array for tx")
Cc: Jason Wang <jasowang@redhat.com>
Signed-off-by: default avatarCong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8cbab92d
Loading
Loading
Loading
Loading
+13 −2
Original line number Diff line number Diff line
@@ -611,6 +611,14 @@ static void tun_queue_purge(struct tun_file *tfile)
	skb_queue_purge(&tfile->sk.sk_error_queue);
}

static void tun_cleanup_tx_array(struct tun_file *tfile)
{
	if (tfile->tx_array.ring.queue) {
		skb_array_cleanup(&tfile->tx_array);
		memset(&tfile->tx_array, 0, sizeof(tfile->tx_array));
	}
}

static void __tun_detach(struct tun_file *tfile, bool clean)
{
	struct tun_file *ntfile;
@@ -657,8 +665,7 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
			    tun->dev->reg_state == NETREG_REGISTERED)
				unregister_netdevice(tun->dev);
		}
		if (tun)
			skb_array_cleanup(&tfile->tx_array);
		tun_cleanup_tx_array(tfile);
		sock_put(&tfile->sk);
	}
}
@@ -700,11 +707,13 @@ static void tun_detach_all(struct net_device *dev)
		/* Drop read queue */
		tun_queue_purge(tfile);
		sock_put(&tfile->sk);
		tun_cleanup_tx_array(tfile);
	}
	list_for_each_entry_safe(tfile, tmp, &tun->disabled, next) {
		tun_enable_queue(tfile);
		tun_queue_purge(tfile);
		sock_put(&tfile->sk);
		tun_cleanup_tx_array(tfile);
	}
	BUG_ON(tun->numdisabled != 0);

@@ -2851,6 +2860,8 @@ static int tun_chr_open(struct inode *inode, struct file * file)

	sock_set_flag(&tfile->sk, SOCK_ZEROCOPY);

	memset(&tfile->tx_array, 0, sizeof(tfile->tx_array));

	return 0;
}