| From 84b4cd0a5c7e31694942222a2b04e36a9175db91 Mon Sep 17 00:00:00 2001 |
| From: Eric Dumazet <edumazet@google.com> |
| Date: Thu, 28 May 2020 14:57:47 -0700 |
| Subject: [PATCH] net: be more gentle about silly gso requests coming from user |
| |
| commit 7c6d2ecbda83150b2036a2b36b21381ad4667762 upstream. |
| |
| Recent change in virtio_net_hdr_to_skb() broke some packetdrill tests. |
| |
| When --mss=XXX option is set, packetdrill always provide gso_type & gso_size |
| for its inbound packets, regardless of packet size. |
| |
| if (packet->tcp && packet->mss) { |
| if (packet->ipv4) |
| gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV4; |
| else |
| gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6; |
| gso.gso_size = packet->mss; |
| } |
| |
| Since many other programs could do the same, relax virtio_net_hdr_to_skb() |
| to no longer return an error, but instead ignore gso settings. |
| |
| This keeps Willem intent to make sure no malicious packet could |
| reach gso stack. |
| |
| Note that TCP stack has a special logic in tcp_set_skb_tso_segs() |
| to clear gso_size for small packets. |
| |
| Fixes: 6dd912f82680 ("net: check untrusted gso_size at kernel entry") |
| Signed-off-by: Eric Dumazet <edumazet@google.com> |
| Cc: Willem de Bruijn <willemb@google.com> |
| Acked-by: Willem de Bruijn <willemb@google.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h |
| index 88997022a4b5..e8a924eeea3d 100644 |
| --- a/include/linux/virtio_net.h |
| +++ b/include/linux/virtio_net.h |
| @@ -109,16 +109,17 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb, |
| |
| if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { |
| u16 gso_size = __virtio16_to_cpu(little_endian, hdr->gso_size); |
| + struct skb_shared_info *shinfo = skb_shinfo(skb); |
| |
| - if (skb->len - p_off <= gso_size) |
| - return -EINVAL; |
| - |
| - skb_shinfo(skb)->gso_size = gso_size; |
| - skb_shinfo(skb)->gso_type = gso_type; |
| + /* Too small packets are not really GSO ones. */ |
| + if (skb->len - p_off > gso_size) { |
| + shinfo->gso_size = gso_size; |
| + shinfo->gso_type = gso_type; |
| |
| - /* Header must be checked, and gso_segs computed. */ |
| - skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY; |
| - skb_shinfo(skb)->gso_segs = 0; |
| + /* Header must be checked, and gso_segs computed. */ |
| + shinfo->gso_type |= SKB_GSO_DODGY; |
| + shinfo->gso_segs = 0; |
| + } |
| } |
| |
| return 0; |
| -- |
| 2.27.0 |
| |