]>
Commit | Line | Data |
---|---|---|
fa55523a GKH |
1 | From foo@baz Thu Dec 14 11:45:40 CET 2017 |
2 | From: Wei Xu <wexu@redhat.com> | |
3 | Date: Fri, 1 Dec 2017 05:10:38 -0500 | |
4 | Subject: tap: free skb if flags error | |
5 | ||
6 | From: Wei Xu <wexu@redhat.com> | |
7 | ||
8 | ||
9 | [ Upstream commit 61d78537843e676e7f56ac6db333db0c0529b892 ] | |
10 | ||
11 | tap_recvmsg() supports accepting skb by msg_control after | |
12 | commit 3b4ba04acca8 ("tap: support receiving skb from msg_control"), | |
13 | the skb if presented should be freed within the function, otherwise | |
14 | it would be leaked. | |
15 | ||
16 | Signed-off-by: Wei Xu <wexu@redhat.com> | |
17 | Reported-by: Matthew Rosato <mjrosato@linux.vnet.ibm.com> | |
18 | Acked-by: Michael S. Tsirkin <mst@redhat.com> | |
19 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
20 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
21 | --- | |
22 | drivers/net/tap.c | 14 ++++++++++---- | |
23 | 1 file changed, 10 insertions(+), 4 deletions(-) | |
24 | ||
25 | --- a/drivers/net/tap.c | |
26 | +++ b/drivers/net/tap.c | |
27 | @@ -829,8 +829,11 @@ static ssize_t tap_do_read(struct tap_qu | |
28 | DEFINE_WAIT(wait); | |
29 | ssize_t ret = 0; | |
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 | goto put; | |
40 | @@ -1154,11 +1157,14 @@ static int tap_recvmsg(struct socket *so | |
41 | size_t total_len, int flags) | |
42 | { | |
43 | struct tap_queue *q = container_of(sock, struct tap_queue, sock); | |
44 | + struct sk_buff *skb = m->msg_control; | |
45 | int ret; | |
46 | - if (flags & ~(MSG_DONTWAIT|MSG_TRUNC)) | |
47 | + if (flags & ~(MSG_DONTWAIT|MSG_TRUNC)) { | |
48 | + if (skb) | |
49 | + kfree_skb(skb); | |
50 | return -EINVAL; | |
51 | - ret = tap_do_read(q, &m->msg_iter, flags & MSG_DONTWAIT, | |
52 | - m->msg_control); | |
53 | + } | |
54 | + ret = tap_do_read(q, &m->msg_iter, flags & MSG_DONTWAIT, skb); | |
55 | if (ret > total_len) { | |
56 | m->msg_flags |= MSG_TRUNC; | |
57 | ret = flags & MSG_TRUNC ? ret : total_len; |