From: Eric Dumazet <eduma...@google.com>

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 <eduma...@google.com>
Cc: Willem de Bruijn <will...@google.com>
Acked-by: Willem de Bruijn <will...@google.com>
Signed-off-by: David S. Miller <da...@davemloft.net>
Cc: Guenter Roeck <li...@roeck-us.net>
Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>
---
 include/linux/virtio_net.h | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
index a16e0bdf77511..d19bfdcf77498 100644
--- a/include/linux/virtio_net.h
+++ b/include/linux/virtio_net.h
@@ -107,16 +107,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.25.1

Reply via email to