|
@@ -981,6 +981,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
|
|
|
struct sk_buff *skb;
|
|
|
size_t len = total_len, align = NET_SKB_PAD, linear;
|
|
|
struct virtio_net_hdr gso = { 0 };
|
|
|
+ int good_linear;
|
|
|
int offset = 0;
|
|
|
int copylen;
|
|
|
bool zerocopy = false;
|
|
@@ -1021,12 +1022,16 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
+ good_linear = SKB_MAX_HEAD(align);
|
|
|
+
|
|
|
if (msg_control) {
|
|
|
/* There are 256 bytes to be copied in skb, so there is
|
|
|
* enough room for skb expand head in case it is used.
|
|
|
* The rest of the buffer is mapped from userspace.
|
|
|
*/
|
|
|
copylen = gso.hdr_len ? gso.hdr_len : GOODCOPY_LEN;
|
|
|
+ if (copylen > good_linear)
|
|
|
+ copylen = good_linear;
|
|
|
linear = copylen;
|
|
|
if (iov_pages(iv, offset + copylen, count) <= MAX_SKB_FRAGS)
|
|
|
zerocopy = true;
|
|
@@ -1034,7 +1039,10 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
|
|
|
|
|
|
if (!zerocopy) {
|
|
|
copylen = len;
|
|
|
- linear = gso.hdr_len;
|
|
|
+ if (gso.hdr_len > good_linear)
|
|
|
+ linear = good_linear;
|
|
|
+ else
|
|
|
+ linear = gso.hdr_len;
|
|
|
}
|
|
|
|
|
|
skb = tun_alloc_skb(tfile, align, copylen, linear, noblock);
|