diff options
author | Eric Dumazet <edumazet@google.com> | 2020-05-28 14:57:47 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-05-28 16:31:30 -0700 |
commit | 7c6d2ecbda83150b2036a2b36b21381ad4667762 (patch) | |
tree | 78135e20eb93f2f4d0eb4489fc0a70d4949c7a0f /include | |
parent | 45ebf73ebcec88a34a778f5feaa0b82b1c76069e (diff) |
net: be more gentle about silly gso requests coming from user
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>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/virtio_net.h | 17 |
1 files changed, 9 insertions, 8 deletions
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 @@ retry: 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; |