]>
Commit | Line | Data |
---|---|---|
59d5af67 | 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
ddad99c9 FG |
2 | From: Wei Xu <wexu@redhat.com> |
3 | Date: Fri, 1 Dec 2017 05:10:37 -0500 | |
59d5af67 | 4 | Subject: [PATCH] tun: free skb in early errors |
ddad99c9 FG |
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 |