]> git.proxmox.com Git - pve-kernel.git/blob - patches/kernel/0009-tun-free-skb-in-early-errors.patch
cherry-pick KVM fix for old CPUs
[pve-kernel.git] / patches / kernel / 0009-tun-free-skb-in-early-errors.patch
1 From ccc0b8662620d562798183b77bcd30125d2d14f3 Mon Sep 17 00:00:00 2001
2 From: Wei Xu <wexu@redhat.com>
3 Date: Fri, 1 Dec 2017 05:10:37 -0500
4 Subject: [PATCH 09/13] tun: free skb in early errors
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 tun_recvmsg() supports accepting skb by msg_control after
10 commit ac77cfd4258f ("tun: support receiving skb through msg_control"),
11 the skb if presented should be freed no matter how far it can go
12 along, otherwise it would be leaked.
13
14 This patch fixes several missed cases.
15
16 Signed-off-by: Wei Xu <wexu@redhat.com>
17 Reported-by: Matthew Rosato <mjrosato@linux.vnet.ibm.com>
18 Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
19 ---
20 drivers/net/tun.c | 24 ++++++++++++++++++------
21 1 file changed, 18 insertions(+), 6 deletions(-)
22
23 diff --git a/drivers/net/tun.c b/drivers/net/tun.c
24 index cb1f7747adad..5143e948d7d1 100644
25 --- a/drivers/net/tun.c
26 +++ b/drivers/net/tun.c
27 @@ -1519,8 +1519,11 @@ static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile,
28
29 tun_debug(KERN_INFO, tun, "tun_do_read\n");
30
31 - if (!iov_iter_count(to))
32 + if (!iov_iter_count(to)) {
33 + if (skb)
34 + kfree_skb(skb);
35 return 0;
36 + }
37
38 if (!skb) {
39 /* Read frames from ring */
40 @@ -1636,22 +1639,24 @@ static int tun_recvmsg(struct socket *sock, struct msghdr *m, size_t total_len,
41 {
42 struct tun_file *tfile = container_of(sock, struct tun_file, socket);
43 struct tun_struct *tun = __tun_get(tfile);
44 + struct sk_buff *skb = m->msg_control;
45 int ret;
46
47 - if (!tun)
48 - return -EBADFD;
49 + if (!tun) {
50 + ret = -EBADFD;
51 + goto out_free_skb;
52 + }
53
54 if (flags & ~(MSG_DONTWAIT|MSG_TRUNC|MSG_ERRQUEUE)) {
55 ret = -EINVAL;
56 - goto out;
57 + goto out_put_tun;
58 }
59 if (flags & MSG_ERRQUEUE) {
60 ret = sock_recv_errqueue(sock->sk, m, total_len,
61 SOL_PACKET, TUN_TX_TIMESTAMP);
62 goto out;
63 }
64 - ret = tun_do_read(tun, tfile, &m->msg_iter, flags & MSG_DONTWAIT,
65 - m->msg_control);
66 + ret = tun_do_read(tun, tfile, &m->msg_iter, flags & MSG_DONTWAIT, skb);
67 if (ret > (ssize_t)total_len) {
68 m->msg_flags |= MSG_TRUNC;
69 ret = flags & MSG_TRUNC ? ret : total_len;
70 @@ -1659,6 +1664,13 @@ static int tun_recvmsg(struct socket *sock, struct msghdr *m, size_t total_len,
71 out:
72 tun_put(tun);
73 return ret;
74 +
75 +out_put_tun:
76 + tun_put(tun);
77 +out_free_skb:
78 + if (skb)
79 + kfree_skb(skb);
80 + return ret;
81 }
82
83 static int tun_peek_len(struct socket *sock)
84 --
85 2.14.2
86