diff options
Diffstat (limited to 'drivers/net/tun.c')
| -rw-r--r-- | drivers/net/tun.c | 44 | 
1 files changed, 22 insertions, 22 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index fbd106edbe5..af372d0957f 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -404,8 +404,8 @@ static void __tun_detach(struct tun_file *tfile, bool clean)  	struct tun_struct *tun;  	struct net_device *dev; -	tun = rcu_dereference_protected(tfile->tun, -					lockdep_rtnl_is_held()); +	tun = rtnl_dereference(tfile->tun); +  	if (tun) {  		u16 index = tfile->queue_index;  		BUG_ON(index >= tun->numqueues); @@ -414,8 +414,7 @@ static void __tun_detach(struct tun_file *tfile, bool clean)  		rcu_assign_pointer(tun->tfiles[index],  				   tun->tfiles[tun->numqueues - 1]);  		rcu_assign_pointer(tfile->tun, NULL); -		ntfile = rcu_dereference_protected(tun->tfiles[index], -						   lockdep_rtnl_is_held()); +		ntfile = rtnl_dereference(tun->tfiles[index]);  		ntfile->queue_index = index;  		--tun->numqueues; @@ -429,8 +428,10 @@ static void __tun_detach(struct tun_file *tfile, bool clean)  		/* Drop read queue */  		skb_queue_purge(&tfile->sk.sk_receive_queue);  		tun_set_real_num_queues(tun); -	} else if (tfile->detached && clean) +	} else if (tfile->detached && clean) {  		tun = tun_enable_queue(tfile); +		sock_put(&tfile->sk); +	}  	if (clean) {  		if (tun && tun->numqueues == 0 && tun->numdisabled == 0 && @@ -458,8 +459,7 @@ static void tun_detach_all(struct net_device *dev)  	int i, n = tun->numqueues;  	for (i = 0; i < n; i++) { -		tfile = rcu_dereference_protected(tun->tfiles[i], -						  lockdep_rtnl_is_held()); +		tfile = rtnl_dereference(tun->tfiles[i]);  		BUG_ON(!tfile);  		wake_up_all(&tfile->wq.wait);  		rcu_assign_pointer(tfile->tun, NULL); @@ -469,8 +469,7 @@ static void tun_detach_all(struct net_device *dev)  	synchronize_net();  	for (i = 0; i < n; i++) { -		tfile = rcu_dereference_protected(tun->tfiles[i], -						  lockdep_rtnl_is_held()); +		tfile = rtnl_dereference(tun->tfiles[i]);  		/* Drop read queue */  		skb_queue_purge(&tfile->sk.sk_receive_queue);  		sock_put(&tfile->sk); @@ -481,6 +480,9 @@ static void tun_detach_all(struct net_device *dev)  		sock_put(&tfile->sk);  	}  	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) @@ -489,7 +491,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file)  	int err;  	err = -EINVAL; -	if (rcu_dereference_protected(tfile->tun, lockdep_rtnl_is_held())) +	if (rtnl_dereference(tfile->tun))  		goto out;  	err = -EBUSY; @@ -1544,6 +1546,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)  	struct net_device *dev;  	int err; +	if (tfile->detached) +		return -EINVAL; +  	dev = __dev_get_by_name(net, ifr->ifr_name);  	if (dev) {  		if (ifr->ifr_flags & IFF_TUN_EXCL) @@ -1738,8 +1743,7 @@ static void tun_detach_filter(struct tun_struct *tun, int n)  	struct tun_file *tfile;  	for (i = 0; i < n; i++) { -		tfile = rcu_dereference_protected(tun->tfiles[i], -						  lockdep_rtnl_is_held()); +		tfile = rtnl_dereference(tun->tfiles[i]);  		sk_detach_filter(tfile->socket.sk);  	} @@ -1752,8 +1756,7 @@ static int tun_attach_filter(struct tun_struct *tun)  	struct tun_file *tfile;  	for (i = 0; i < tun->numqueues; i++) { -		tfile = rcu_dereference_protected(tun->tfiles[i], -						  lockdep_rtnl_is_held()); +		tfile = rtnl_dereference(tun->tfiles[i]);  		ret = sk_attach_filter(&tun->fprog, tfile->socket.sk);  		if (ret) {  			tun_detach_filter(tun, i); @@ -1771,8 +1774,7 @@ static void tun_set_sndbuf(struct tun_struct *tun)  	int i;  	for (i = 0; i < tun->numqueues; i++) { -		tfile = rcu_dereference_protected(tun->tfiles[i], -						lockdep_rtnl_is_held()); +		tfile = rtnl_dereference(tun->tfiles[i]);  		tfile->socket.sk->sk_sndbuf = tun->sndbuf;  	}  } @@ -1789,13 +1791,10 @@ static int tun_set_queue(struct file *file, struct ifreq *ifr)  		tun = tfile->detached;  		if (!tun)  			ret = -EINVAL; -		else if (tun_not_capable(tun)) -			ret = -EPERM;  		else  			ret = tun_attach(tun, file);  	} else if (ifr->ifr_flags & IFF_DETACH_QUEUE) { -		tun = rcu_dereference_protected(tfile->tun, -						lockdep_rtnl_is_held()); +		tun = rtnl_dereference(tfile->tun);  		if (!tun || !(tun->flags & TUN_TAP_MQ))  			ret = -EINVAL;  		else @@ -1880,10 +1879,11 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,  		/* Disable/Enable persist mode. Keep an extra reference to the  		 * module to prevent the module being unprobed.  		 */ -		if (arg) { +		if (arg && !(tun->flags & TUN_PERSIST)) {  			tun->flags |= TUN_PERSIST;  			__module_get(THIS_MODULE); -		} else { +		} +		if (!arg && (tun->flags & TUN_PERSIST)) {  			tun->flags &= ~TUN_PERSIST;  			module_put(THIS_MODULE);  		}  |