From: Ankit Garg nktgrg@google.com
The driver currently assumes that the skb queue mapping is within the range of configured TX queues. However, the stack may provide an index that exceeds the number of active queues.
In GQI format, an out-of-range index triggered a warning but continues to dereference tx array, potentially causing a crash like below:
[ 6.700970] Call Trace: [ 6.703576] ? __warn+0x94/0xe0 [ 6.706863] ? gve_tx+0xa9f/0xc30 [gve] [ 6.712223] ? gve_tx+0xa9f/0xc30 [gve] [ 6.716197] ? report_bug+0xb1/0xe0 [ 6.721195] ? do_error_trap+0x9e/0xd0 [ 6.725084] ? do_invalid_op+0x36/0x40 [ 6.730355] ? gve_tx+0xa9f/0xc30 [gve] [ 6.734353] ? invalid_op+0x14/0x20 [ 6.739372] ? gve_tx+0xa9f/0xc30 [gve] [ 6.743350] ? netif_skb_features+0xcf/0x2a0 [ 6.749137] dev_hard_start_xmit+0xd7/0x240
Change that behavior to log a warning and drop the packet.
Cc: stable@vger.kernel.org Fixes: f5cedc84a30d ("gve: Add transmit and receive support") Signed-off-by: Ankit Garg nktgrg@google.com Reviewed-by: Harshitha Ramamurthy hramamurthy@google.com Signed-off-by: Joshua Washington joshwash@google.com --- drivers/net/ethernet/google/gve/gve_tx.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/google/gve/gve_tx.c b/drivers/net/ethernet/google/gve/gve_tx.c index 97efc8d..30d1686 100644 --- a/drivers/net/ethernet/google/gve/gve_tx.c +++ b/drivers/net/ethernet/google/gve/gve_tx.c @@ -739,12 +739,18 @@ drop: netdev_tx_t gve_tx(struct sk_buff *skb, struct net_device *dev) { struct gve_priv *priv = netdev_priv(dev); + u16 qid = skb_get_queue_mapping(skb); struct gve_tx_ring *tx; int nsegs;
- WARN(skb_get_queue_mapping(skb) >= priv->tx_cfg.num_queues, - "skb queue index out of range"); - tx = &priv->tx[skb_get_queue_mapping(skb)]; + if (unlikely(qid >= priv->tx_cfg.num_queues)) { + net_warn_ratelimited("%s: skb qid %d out of range, num tx queue %d. dropping packet", + dev->name, qid, priv->tx_cfg.num_queues); + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + + tx = &priv->tx[qid]; if (unlikely(gve_maybe_stop_tx(priv, tx, skb))) { /* We need to ring the txq doorbell -- we have stopped the Tx * queue for want of resources, but prior calls to gve_tx()