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 <[email protected]> Reviewed-by: Praveen Kaligineedi <[email protected]> Reviewed-by: Harshitha Ramamurthy <[email protected]> Reviewed-by: Willem de Bruijn <[email protected]> Suggested-by: Eric Dumazet <[email protected]> Acked-by: Andrei Vagin <[email protected]> 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/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent f6b2f57 commit 1b9f756

File tree

1 file changed

+5
-15
lines changed

1 file changed

+5
-15
lines changed

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)