diff options
Diffstat (limited to 'drivers/net/tun.c')
-rw-r--r-- | drivers/net/tun.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 7cb105c103fe..782e38bfc1ee 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
@@ -981,6 +981,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
981 | struct sk_buff *skb; | 981 | struct sk_buff *skb; |
982 | size_t len = total_len, align = NET_SKB_PAD, linear; | 982 | size_t len = total_len, align = NET_SKB_PAD, linear; |
983 | struct virtio_net_hdr gso = { 0 }; | 983 | struct virtio_net_hdr gso = { 0 }; |
984 | int good_linear; | ||
984 | int offset = 0; | 985 | int offset = 0; |
985 | int copylen; | 986 | int copylen; |
986 | bool zerocopy = false; | 987 | bool zerocopy = false; |
@@ -1021,12 +1022,16 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
1021 | return -EINVAL; | 1022 | return -EINVAL; |
1022 | } | 1023 | } |
1023 | 1024 | ||
1025 | good_linear = SKB_MAX_HEAD(align); | ||
1026 | |||
1024 | if (msg_control) { | 1027 | if (msg_control) { |
1025 | /* There are 256 bytes to be copied in skb, so there is | 1028 | /* There are 256 bytes to be copied in skb, so there is |
1026 | * enough room for skb expand head in case it is used. | 1029 | * enough room for skb expand head in case it is used. |
1027 | * The rest of the buffer is mapped from userspace. | 1030 | * The rest of the buffer is mapped from userspace. |
1028 | */ | 1031 | */ |
1029 | copylen = gso.hdr_len ? gso.hdr_len : GOODCOPY_LEN; | 1032 | copylen = gso.hdr_len ? gso.hdr_len : GOODCOPY_LEN; |
1033 | if (copylen > good_linear) | ||
1034 | copylen = good_linear; | ||
1030 | linear = copylen; | 1035 | linear = copylen; |
1031 | if (iov_pages(iv, offset + copylen, count) <= MAX_SKB_FRAGS) | 1036 | if (iov_pages(iv, offset + copylen, count) <= MAX_SKB_FRAGS) |
1032 | zerocopy = true; | 1037 | zerocopy = true; |
@@ -1034,7 +1039,10 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
1034 | 1039 | ||
1035 | if (!zerocopy) { | 1040 | if (!zerocopy) { |
1036 | copylen = len; | 1041 | copylen = len; |
1037 | linear = gso.hdr_len; | 1042 | if (gso.hdr_len > good_linear) |
1043 | linear = good_linear; | ||
1044 | else | ||
1045 | linear = gso.hdr_len; | ||
1038 | } | 1046 | } |
1039 | 1047 | ||
1040 | skb = tun_alloc_skb(tfile, align, copylen, linear, noblock); | 1048 | skb = tun_alloc_skb(tfile, align, copylen, linear, noblock); |