TSO packets are not checked against the device limits before use.
The device requires an MSS of 88 to 9728 bytes and a payload of at
most 262143 bytes, as noted in the Linux driver. A packet outside
these limits triggers malicious driver detection, which drops it and
disables the datapath, stalling all queues.

The missing checks also break the driver itself: a tso_segsz of 0
divides by zero in gve_tx_validate_descs(), headers longer than 255
bytes are truncated by the 8-bit header_len field, and headers not
contained in the first segment give gve_tx_validate_descs() a
negative first segment length.

Drop TSO packets that violate these limits and count them as
invalid_pkts.

Fixes: 403c671a46b6 ("net/gve: support TSO in DQO RDA")
Fixes: be8f0eb81f98 ("net/gve: fix DQO TSO descriptor limit")
Cc: [email protected]

Signed-off-by: Tathagat Priyadarshi <[email protected]>
---
 drivers/net/gve/base/gve_desc_dqo.h |  1 +
 drivers/net/gve/gve_tx_dqo.c        | 14 +++++++++++++-
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/net/gve/base/gve_desc_dqo.h 
b/drivers/net/gve/base/gve_desc_dqo.h
index d50d88765e..53e394f01c 100644
--- a/drivers/net/gve/base/gve_desc_dqo.h
+++ b/drivers/net/gve/base/gve_desc_dqo.h
@@ -14,6 +14,7 @@
 #define GVE_TX_MIN_TSO_MSS_DQO 88
 #define GVE_TX_MIN_PKT_SIZE_DQO 17
 #define GVE_TX_MAX_PKT_SIZE_DQO 9728
+#define GVE_TX_MAX_TSO_LEN_DQO ((256 * 1024) - 1)
 
 /* Basic TX descriptor (DTYPE 0x0C) */
 struct gve_tx_pkt_desc_dqo {
diff --git a/drivers/net/gve/gve_tx_dqo.c b/drivers/net/gve/gve_tx_dqo.c
index c23b222ada..0b328e4af4 100644
--- a/drivers/net/gve/gve_tx_dqo.c
+++ b/drivers/net/gve/gve_tx_dqo.c
@@ -130,11 +130,23 @@ gve_tx_clean_descs_dqo(struct gve_tx_queue *txq, uint16_t 
nb_descs) {
 static inline bool
 gve_tx_validate_pkt(const struct rte_mbuf *tx_pkt, bool is_tso)
 {
+       uint32_t headlen;
+
        if (!is_tso)
                return tx_pkt->pkt_len >= GVE_TX_MIN_PKT_SIZE_DQO &&
                       tx_pkt->pkt_len <= GVE_TX_MAX_PKT_SIZE_DQO;
 
-       return true;
+       /* Headers must be present, fit the context descriptor, and be
+        * contained in the first segment; the payload must not be empty.
+        */
+       headlen = tx_pkt->l2_len + tx_pkt->l3_len + tx_pkt->l4_len;
+       if (tx_pkt->l4_len == 0 || headlen > GVE_TX_MAX_HDR_SIZE_DQO ||
+           tx_pkt->data_len < headlen || tx_pkt->pkt_len <= headlen)
+               return false;
+
+       return tx_pkt->pkt_len - headlen <= GVE_TX_MAX_TSO_LEN_DQO &&
+              tx_pkt->tso_segsz >= GVE_TX_MIN_TSO_MSS_DQO &&
+              tx_pkt->tso_segsz <= GVE_TX_MAX_PKT_SIZE_DQO;
 }
 
 /* Max descriptors a single packet may use. A larger packet can never pass
-- 
2.43.0

Reply via email to