Skip to content

Commit 1b9f756

Browse files
josh8551021kuba-moo
authored andcommitted
gve: ignore nonrelevant GSO type bits when processing TSO headers
TSO currently fails when the skb's gso_type field has more than one bit set. TSO packets can be passed from userspace using PF_PACKET, TUNTAP and a few others, using virtio_net_hdr (e.g., PACKET_VNET_HDR). This includes virtualization, such as QEMU, a real use-case. The gso_type and gso_size fields as passed from userspace in virtio_net_hdr are not trusted blindly by the kernel. It adds gso_type |= SKB_GSO_DODGY to force the packet to enter the software GSO stack for verification. This issue might similarly come up when the CWR bit is set in the TCP header for congestion control, causing the SKB_GSO_TCP_ECN gso_type bit to be set. Fixes: a57e5de ("gve: DQO: Add TX path") Signed-off-by: Joshua Washington <joshwash@google.com> Reviewed-by: Praveen Kaligineedi <pkaligineedi@google.com> Reviewed-by: Harshitha Ramamurthy <hramamurthy@google.com> Reviewed-by: Willem de Bruijn <willemb@google.com> Suggested-by: Eric Dumazet <edumazet@google.com> Acked-by: Andrei Vagin <avagin@gmail.com> v2 - Remove unnecessary comments, remove line break between fixes tag and signoffs. v3 - Add back unrelated empty line removal. Link: https://lore.kernel.org/r/20240610225729.2985343-1-joshwash@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent f6b2f57 commit 1b9f756

1 file changed

Lines changed: 5 additions & 15 deletions

File tree

drivers/net/ethernet/google/gve/gve_tx_dqo.c

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -555,28 +555,18 @@ static int gve_prep_tso(struct sk_buff *skb)
555555
if (unlikely(skb_shinfo(skb)->gso_size < GVE_TX_MIN_TSO_MSS_DQO))
556556
return -1;
557557

558+
if (!(skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))
559+
return -EINVAL;
560+
558561
/* Needed because we will modify header. */
559562
err = skb_cow_head(skb, 0);
560563
if (err < 0)
561564
return err;
562565

563566
tcp = tcp_hdr(skb);
564-
565-
/* Remove payload length from checksum. */
566567
paylen = skb->len - skb_transport_offset(skb);
567-
568-
switch (skb_shinfo(skb)->gso_type) {
569-
case SKB_GSO_TCPV4:
570-
case SKB_GSO_TCPV6:
571-
csum_replace_by_diff(&tcp->check,
572-
(__force __wsum)htonl(paylen));
573-
574-
/* Compute length of segmentation header. */
575-
header_len = skb_tcp_all_headers(skb);
576-
break;
577-
default:
578-
return -EINVAL;
579-
}
568+
csum_replace_by_diff(&tcp->check, (__force __wsum)htonl(paylen));
569+
header_len = skb_tcp_all_headers(skb);
580570

581571
if (unlikely(header_len > GVE_TX_MAX_HDR_SIZE_DQO))
582572
return -EINVAL;

0 commit comments

Comments
 (0)