diff options
Diffstat (limited to 'drivers/net/tun.c')
| -rw-r--r-- | drivers/net/tun.c | 17 | 
1 files changed, 13 insertions, 4 deletions
| diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 93c5d72711b0..74d7f76d14a3 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -359,7 +359,7 @@ static void tun_free_netdev(struct net_device *dev)  {  	struct tun_struct *tun = netdev_priv(dev); -	sock_put(tun->socket.sk); +	sk_release_kernel(tun->socket.sk);  }  /* Net device open. */ @@ -531,7 +531,7 @@ static void tun_net_init(struct net_device *dev)  		ether_setup(dev);  		dev->priv_flags &= ~IFF_TX_SKB_SHARING; -		random_ether_addr(dev->dev_addr); +		eth_hw_addr_random(dev);  		dev->tx_queue_len = TUN_READQ_SIZE;  /* We prefer our own queue length */  		break; @@ -980,10 +980,18 @@ static int tun_recvmsg(struct kiocb *iocb, struct socket *sock,  	return ret;  } +static int tun_release(struct socket *sock) +{ +	if (sock->sk) +		sock_put(sock->sk); +	return 0; +} +  /* Ops structure to mimic raw sockets with tun */  static const struct proto_ops tun_socket_ops = {  	.sendmsg = tun_sendmsg,  	.recvmsg = tun_recvmsg, +	.release = tun_release,  };  static struct proto tun_proto = { @@ -1110,10 +1118,11 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)  		tun->vnet_hdr_sz = sizeof(struct virtio_net_hdr);  		err = -ENOMEM; -		sk = sk_alloc(net, AF_UNSPEC, GFP_KERNEL, &tun_proto); +		sk = sk_alloc(&init_net, AF_UNSPEC, GFP_KERNEL, &tun_proto);  		if (!sk)  			goto err_free_dev; +		sk_change_net(sk, net);  		tun->socket.wq = &tun->wq;  		init_waitqueue_head(&tun->wq.wait);  		tun->socket.ops = &tun_socket_ops; @@ -1174,7 +1183,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)  	return 0;   err_free_sk: -	sock_put(sk); +	tun_free_netdev(dev);   err_free_dev:  	free_netdev(dev);   failed: | 
