aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/tun.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/tun.c')
-rw-r--r--drivers/net/tun.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 95749006d687..4f4a842a1c9c 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1952,8 +1952,11 @@ static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile,
1952 1952
1953 tun_debug(KERN_INFO, tun, "tun_do_read\n"); 1953 tun_debug(KERN_INFO, tun, "tun_do_read\n");
1954 1954
1955 if (!iov_iter_count(to)) 1955 if (!iov_iter_count(to)) {
1956 if (skb)
1957 kfree_skb(skb);
1956 return 0; 1958 return 0;
1959 }
1957 1960
1958 if (!skb) { 1961 if (!skb) {
1959 /* Read frames from ring */ 1962 /* Read frames from ring */
@@ -2069,22 +2072,24 @@ static int tun_recvmsg(struct socket *sock, struct msghdr *m, size_t total_len,
2069{ 2072{
2070 struct tun_file *tfile = container_of(sock, struct tun_file, socket); 2073 struct tun_file *tfile = container_of(sock, struct tun_file, socket);
2071 struct tun_struct *tun = tun_get(tfile); 2074 struct tun_struct *tun = tun_get(tfile);
2075 struct sk_buff *skb = m->msg_control;
2072 int ret; 2076 int ret;
2073 2077
2074 if (!tun) 2078 if (!tun) {
2075 return -EBADFD; 2079 ret = -EBADFD;
2080 goto out_free_skb;
2081 }
2076 2082
2077 if (flags & ~(MSG_DONTWAIT|MSG_TRUNC|MSG_ERRQUEUE)) { 2083 if (flags & ~(MSG_DONTWAIT|MSG_TRUNC|MSG_ERRQUEUE)) {
2078 ret = -EINVAL; 2084 ret = -EINVAL;
2079 goto out; 2085 goto out_put_tun;
2080 } 2086 }
2081 if (flags & MSG_ERRQUEUE) { 2087 if (flags & MSG_ERRQUEUE) {
2082 ret = sock_recv_errqueue(sock->sk, m, total_len, 2088 ret = sock_recv_errqueue(sock->sk, m, total_len,
2083 SOL_PACKET, TUN_TX_TIMESTAMP); 2089 SOL_PACKET, TUN_TX_TIMESTAMP);
2084 goto out; 2090 goto out;
2085 } 2091 }
2086 ret = tun_do_read(tun, tfile, &m->msg_iter, flags & MSG_DONTWAIT, 2092 ret = tun_do_read(tun, tfile, &m->msg_iter, flags & MSG_DONTWAIT, skb);
2087 m->msg_control);
2088 if (ret > (ssize_t)total_len) { 2093 if (ret > (ssize_t)total_len) {
2089 m->msg_flags |= MSG_TRUNC; 2094 m->msg_flags |= MSG_TRUNC;
2090 ret = flags & MSG_TRUNC ? ret : total_len; 2095 ret = flags & MSG_TRUNC ? ret : total_len;
@@ -2092,6 +2097,13 @@ static int tun_recvmsg(struct socket *sock, struct msghdr *m, size_t total_len,
2092out: 2097out:
2093 tun_put(tun); 2098 tun_put(tun);
2094 return ret; 2099 return ret;
2100
2101out_put_tun:
2102 tun_put(tun);
2103out_free_skb:
2104 if (skb)
2105 kfree_skb(skb);
2106 return ret;
2095} 2107}
2096 2108
2097static int tun_peek_len(struct socket *sock) 2109static int tun_peek_len(struct socket *sock)