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

Commit 38231b7a authored by Eric W. Biederman's avatar Eric W. Biederman Committed by David S. Miller
Browse files

tun: Make tun_net_xmit atomic wrt tun_attach && tun_detach



Currently this small race allows for a packet to be received when we
detach from an tun device and still be enqueued.  Not especially
important but not what the code is trying to do.

Signed-off-by: default avatarEric W. Biederman <ebiederm@aristanetworks.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 36b50bab
Loading
Loading
Loading
Loading
+17 −7
Original line number Diff line number Diff line
@@ -115,25 +115,33 @@ static int tun_attach(struct tun_struct *tun, struct file *file)
{
	struct tun_file *tfile = file->private_data;
	const struct cred *cred = current_cred();
	int err;

	ASSERT_RTNL();

	if (tfile->tun)
		return -EINVAL;

	if (tun->tfile)
		return -EBUSY;

	/* Check permissions */
	if (((tun->owner != -1 && cred->euid != tun->owner) ||
	     (tun->group != -1 && cred->egid != tun->group)) &&
		!capable(CAP_NET_ADMIN))
		return -EPERM;

	netif_tx_lock_bh(tun->dev);

	err = -EINVAL;
	if (tfile->tun)
		goto out;

	err = -EBUSY;
	if (tun->tfile)
		goto out;

	err = 0;
	tfile->tun = tun;
	tun->tfile = tfile;

	return 0;
out:
	netif_tx_unlock_bh(tun->dev);
	return err;
}

static void __tun_detach(struct tun_struct *tun)
@@ -141,8 +149,10 @@ static void __tun_detach(struct tun_struct *tun)
	struct tun_file *tfile = tun->tfile;

	/* Detach from net device */
	netif_tx_lock_bh(tun->dev);
	tfile->tun = NULL;
	tun->tfile = NULL;
	netif_tx_unlock_bh(tun->dev);

	/* Drop read queue */
	skb_queue_purge(&tun->readq);