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 DQO format, driver doesn't perform any validation and continues to dereference tx array, potentially causing a crash like below (trace is from GQI format, but how we handle OOB queue is same in both formats).
[ 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: a57e5de476be ("gve: DQO: Add TX path") 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_dqo.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/google/gve/gve_tx_dqo.c b/drivers/net/ethernet/google/gve/gve_tx_dqo.c index 40b89b3..8ebcc84 100644 --- a/drivers/net/ethernet/google/gve/gve_tx_dqo.c +++ b/drivers/net/ethernet/google/gve/gve_tx_dqo.c @@ -1045,9 +1045,16 @@ static void gve_xsk_reorder_queue_pop_dqo(struct gve_tx_ring *tx) netdev_tx_t gve_tx_dqo(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;
- 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_try_tx_skb(priv, tx, skb) < 0)) { /* We need to ring the txq doorbell -- we have stopped the Tx * queue for want of resources, but prior calls to gve_tx() -- 2.52.0.351.gbe84eed79e-goog