diff options
Diffstat (limited to 'recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.24/0020-macvtap-zerocopy-validate-vectors-before-building-sk.patch')
-rw-r--r-- | recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.24/0020-macvtap-zerocopy-validate-vectors-before-building-sk.patch | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.24/0020-macvtap-zerocopy-validate-vectors-before-building-sk.patch b/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.24/0020-macvtap-zerocopy-validate-vectors-before-building-sk.patch new file mode 100644 index 00000000..a46ddcbc --- /dev/null +++ b/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.24/0020-macvtap-zerocopy-validate-vectors-before-building-sk.patch | |||
@@ -0,0 +1,84 @@ | |||
1 | From c93ad33631e3efbb6f02f24c6b6817227b2c9252 Mon Sep 17 00:00:00 2001 | ||
2 | From: Jason Wang <jasowang@redhat.com> | ||
3 | Date: Wed, 2 May 2012 11:42:15 +0800 | ||
4 | Subject: [PATCH 020/109] macvtap: zerocopy: validate vectors before building | ||
5 | skb | ||
6 | |||
7 | commit b92946e2919134ebe2a4083e4302236295ea2a73 upstream. | ||
8 | |||
9 | There're several reasons that the vectors need to be validated: | ||
10 | |||
11 | - Return error when caller provides vectors whose num is greater than UIO_MAXIOV. | ||
12 | - Linearize part of skb when userspace provides vectors grater than MAX_SKB_FRAGS. | ||
13 | - Return error when userspace provides vectors whose total length may exceed | ||
14 | - MAX_SKB_FRAGS * PAGE_SIZE. | ||
15 | |||
16 | Signed-off-by: Jason Wang <jasowang@redhat.com> | ||
17 | Signed-off-by: Michael S. Tsirkin <mst@redhat.com> | ||
18 | Signed-off-by: Ben Hutchings <ben@decadent.org.uk> | ||
19 | --- | ||
20 | drivers/net/macvtap.c | 25 +++++++++++++++++++++---- | ||
21 | 1 files changed, 21 insertions(+), 4 deletions(-) | ||
22 | |||
23 | diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c | ||
24 | index 7fecd66..26106c0 100644 | ||
25 | --- a/drivers/net/macvtap.c | ||
26 | +++ b/drivers/net/macvtap.c | ||
27 | @@ -528,9 +528,10 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from, | ||
28 | } | ||
29 | base = (unsigned long)from->iov_base + offset; | ||
30 | size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT; | ||
31 | + if (i + size > MAX_SKB_FRAGS) | ||
32 | + return -EMSGSIZE; | ||
33 | num_pages = get_user_pages_fast(base, size, 0, &page[i]); | ||
34 | - if ((num_pages != size) || | ||
35 | - (num_pages > MAX_SKB_FRAGS - skb_shinfo(skb)->nr_frags)) { | ||
36 | + if (num_pages != size) { | ||
37 | for (i = 0; i < num_pages; i++) | ||
38 | put_page(page[i]); | ||
39 | return -EFAULT; | ||
40 | @@ -650,7 +651,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, | ||
41 | int err; | ||
42 | struct virtio_net_hdr vnet_hdr = { 0 }; | ||
43 | int vnet_hdr_len = 0; | ||
44 | - int copylen; | ||
45 | + int copylen = 0; | ||
46 | bool zerocopy = false; | ||
47 | |||
48 | if (q->flags & IFF_VNET_HDR) { | ||
49 | @@ -679,15 +680,31 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, | ||
50 | if (unlikely(len < ETH_HLEN)) | ||
51 | goto err; | ||
52 | |||
53 | + err = -EMSGSIZE; | ||
54 | + if (unlikely(count > UIO_MAXIOV)) | ||
55 | + goto err; | ||
56 | + | ||
57 | if (m && m->msg_control && sock_flag(&q->sk, SOCK_ZEROCOPY)) | ||
58 | zerocopy = true; | ||
59 | |||
60 | if (zerocopy) { | ||
61 | + /* Userspace may produce vectors with count greater than | ||
62 | + * MAX_SKB_FRAGS, so we need to linearize parts of the skb | ||
63 | + * to let the rest of data to be fit in the frags. | ||
64 | + */ | ||
65 | + if (count > MAX_SKB_FRAGS) { | ||
66 | + copylen = iov_length(iv, count - MAX_SKB_FRAGS); | ||
67 | + if (copylen < vnet_hdr_len) | ||
68 | + copylen = 0; | ||
69 | + else | ||
70 | + copylen -= vnet_hdr_len; | ||
71 | + } | ||
72 | /* There are 256 bytes to be copied in skb, so there is enough | ||
73 | * room for skb expand head in case it is used. | ||
74 | * The rest buffer is mapped from userspace. | ||
75 | */ | ||
76 | - copylen = vnet_hdr.hdr_len; | ||
77 | + if (copylen < vnet_hdr.hdr_len) | ||
78 | + copylen = vnet_hdr.hdr_len; | ||
79 | if (!copylen) | ||
80 | copylen = GOODCOPY_LEN; | ||
81 | } else | ||
82 | -- | ||
83 | 1.7.7.6 | ||
84 | |||