summaryrefslogtreecommitdiffstats
path: root/drivers/net/tun.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2012-03-19 17:41:24 +0100
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-03-19 17:41:24 +0100
commit9ce28d827f74d0acdd058bded8bab5309b0f5c8f (patch)
tree634f22e8df9c7fd3966b3639e3e997436751ca50 /drivers/net/tun.c
parent[media] radio-sf16fmr2: fix session mismatches (diff)
parentLinux 3.3 (diff)
downloadlinux-9ce28d827f74d0acdd058bded8bab5309b0f5c8f.tar.xz
linux-9ce28d827f74d0acdd058bded8bab5309b0f5c8f.zip
Merge tag 'v3.3' into staging/for_v3.4
* tag 'v3.3': (1646 commits) Linux 3.3 Don't limit non-nested epoll paths netfilter: ctnetlink: fix race between delete and timeout expiration ipv6: Don't dev_hold(dev) in ip6_mc_find_dev_rcu. nilfs2: fix NULL pointer dereference in nilfs_load_super_block() nilfs2: clamp ns_r_segments_percentage to [1, 99] afs: Remote abort can cause BUG in rxrpc code afs: Read of file returns EBADMSG C6X: remove dead code from entry.S wimax/i2400m: fix erroneous NETDEV_TX_BUSY use net/hyperv: fix erroneous NETDEV_TX_BUSY use net/usbnet: reserve headroom on rx skbs bnx2x: fix memory leak in bnx2x_init_firmware() bnx2x: fix a crash on corrupt firmware file sch_sfq: revert dont put new flow at the end of flows ipv6: fix icmp6_dst_alloc() MAINTAINERS: Add Serge as maintainer of capabilities drivers/video/backlight/s6e63m0.c: fix corruption storing gamma mode MAINTAINERS: add entry for exynos mipi display drivers MAINTAINERS: fix link to Gustavo Padovans tree ...
Diffstat (limited to 'drivers/net/tun.c')
-rw-r--r--drivers/net/tun.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 93c5d72711b0..2d7601dd6660 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. */
@@ -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: