mirror of
https://github.com/torvalds/linux.git
synced 2026-10-07 19:16:02 +02:00
Merge branch 'gve-dqo-fix-handling-of-out-of-range-tso-mss'
Eric Dumazet says: ==================== gve: DQO: fix handling of out of range TSO MSS The DQO TX path assumes that the MSS of a TSO packet is within the range supported by the device, [88, 9728]. This holds for locally generated traffic, but not for packets coming from a tap or from a packet socket: virtio_net_hdr_to_skb() takes gso_size from user space and only enforces a minimum, layer 2 forwarding does not check the MTU of GSO packets, and gso_features_check() bounds skb->len and gso_segs but never gso_size. Patch 1, from Eddie Phillips, deals with the lower bound. It moves the existing test out of gve_prep_tso() into gve_features_check_dqo(), so that these packets are segmented in software instead of being dropped. Patch 2 deals with the upper bound, which is currently not checked at all. gve_tx_fill_tso_ctx_desc() stores gso_size into a 14 bits wide field, so that an MSS of 16384 silently becomes zero. Falling back to software segmentation is not an option here, because skb_segment() splits at gso_size regardless of the MTU, and would only replace an invalid TSO packet by non TSO packets larger than the 9728 bytes the device supports. These packets are dropped instead. As noted in patch 2, oversized non TSO packets can still reach the device whenever the stack segments in software. This is not specific to gve and is better fixed in the core, so a patch for __is_skb_forwardable() will be sent separately for net-next. ==================== Link: https://patch.msgid.link/20260924004252.1196328-1-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
488089055b
|
|
@ -14,6 +14,11 @@
|
|||
#define GVE_TX_MAX_HDR_SIZE_DQO 255
|
||||
#define GVE_TX_MIN_TSO_MSS_DQO 88
|
||||
|
||||
/* HW limit. This also has to fit in the 14 bits of the mss field of
|
||||
* struct gve_tx_tso_context_desc_dqo.
|
||||
*/
|
||||
#define GVE_TX_MAX_TSO_MSS_DQO 9728
|
||||
|
||||
#ifndef __LITTLE_ENDIAN_BITFIELD
|
||||
#error "Only little endian supported"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -577,15 +577,18 @@ static int gve_prep_tso(struct sk_buff *skb)
|
|||
int header_len;
|
||||
int err;
|
||||
|
||||
/* Note: HW requires MSS (gso_size) to be <= 9728 and the total length
|
||||
* of the TSO to be <= 262143.
|
||||
/* Note: HW requires the total length of the TSO to be <= 262143,
|
||||
* this is enforced by netif_set_tso_max_size().
|
||||
*
|
||||
* However, we don't validate these because:
|
||||
* - Hypervisor enforces a limit of 9K MTU
|
||||
* - Kernel will not produce a TSO larger than 64k
|
||||
* MSS (gso_size) can not be trusted: packets forwarded from a tap or
|
||||
* injected by a packet socket can carry an arbitrary value, while the
|
||||
* mss field of the TSO context descriptor is only 14 bits wide.
|
||||
*
|
||||
* A too big MSS is dropped here instead of being rejected from
|
||||
* gve_features_check_dqo(), because software segmentation would
|
||||
* produce packets larger than the device can send.
|
||||
*/
|
||||
|
||||
if (unlikely(shinfo->gso_size < GVE_TX_MIN_TSO_MSS_DQO))
|
||||
if (unlikely(shinfo->gso_size > GVE_TX_MAX_TSO_MSS_DQO))
|
||||
return -1;
|
||||
|
||||
/* Needed because we will modify header. */
|
||||
|
|
@ -925,6 +928,9 @@ static bool gve_can_send_tso(const struct sk_buff *skb)
|
|||
int header_len;
|
||||
int i;
|
||||
|
||||
if (unlikely(gso_size < GVE_TX_MIN_TSO_MSS_DQO))
|
||||
return false;
|
||||
|
||||
/* Must match the header length programmed by gve_prep_tso(). */
|
||||
if (skb_is_gso_tcp(skb))
|
||||
header_len = skb_tcp_all_headers(skb);
|
||||
|
|
@ -972,7 +978,17 @@ netdev_features_t gve_features_check_dqo(struct sk_buff *skb,
|
|||
struct net_device *dev,
|
||||
netdev_features_t features)
|
||||
{
|
||||
if (skb_is_gso(skb) && !gve_can_send_tso(skb))
|
||||
if (!skb_is_gso(skb))
|
||||
return features;
|
||||
|
||||
/* Keep the GSO bits for a too big MSS, so that gve_prep_tso() drops
|
||||
* the packet: software segmentation would give packets larger than
|
||||
* the device can send.
|
||||
*/
|
||||
if (skb_shinfo(skb)->gso_size > GVE_TX_MAX_TSO_MSS_DQO)
|
||||
return features;
|
||||
|
||||
if (!gve_can_send_tso(skb))
|
||||
return features & ~NETIF_F_GSO_MASK;
|
||||
|
||||
return features;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user