axienet_start_xmit_dmaengine() bumps lp->tx_ring_head before skb_to_sgvec(), dma_map_sg() and device_prep_slave_sg(), and none of their error paths undo it. The skb is freed and nothing is submitted, but the slot stays claimed. axienet_dma_tx_cb() walks tx_ring_tail once per completion, so the next completion lands on the abandoned slot and dereferences whatever skb pointer is left there: NULL if the slot was never used or was already completed, or a stale skb that gets consumed a second time. Every completion after that is accounted against the wrong slot. dma_map_sg() and device_prep_slave_sg() can fail at runtime, and so can skb_to_sgvec() on a malformed skb. Only advance tx_ring_head once those have succeeded. The completion callback can't run before dmaengine_submit(), so claiming the slot just before that is fine. dmaengine_submit() itself can also fail on xilinx_dma after a channel error, and its return isn't checked either. That's a separate problem and isn't changed here. This was found by the Sashiko AI review of the skbuff BUG_ON() series. Fixes: 6a91b846af85 ("net: axienet: Introduce dmaengine support") Link: https://lore.kernel.org/all/20261007-b4-skbuff-bug-on-v2-0-b9a5f732895b@toxicpanda.com/ Cc: stable@vger.kernel.org Assisted-by: LLM Signed-off-by: Josef Bacik --- Compile-tested only, I don't have the hardware. The bug is in the error paths, which are easy to see from the diff: every goto after the old increment returns without submitting anything. Thanks, Josef --- drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 09443623a3e2..a5800409e45a 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -929,7 +929,6 @@ axienet_start_xmit_dmaengine(struct sk_buff *skb, struct net_device *ndev) if (!skbuf_dma) goto xmit_error_drop_skb; - lp->tx_ring_head++; sg_init_table(skbuf_dma->sgl, sg_len); ret = skb_to_sgvec(skb, skbuf_dma->sgl, 0, skb->len); if (ret < 0) @@ -965,6 +964,10 @@ axienet_start_xmit_dmaengine(struct sk_buff *skb, struct net_device *ndev) skbuf_dma->sg_len = sg_len; dma_tx_desc->callback_param = lp; dma_tx_desc->callback_result = axienet_dma_tx_cb; + /* Claim the ring slot only after the steps above that can fail. The + * completion callback can't run before dmaengine_submit(). + */ + lp->tx_ring_head++; txq = skb_get_tx_queue(lp->ndev, skb); netdev_tx_sent_queue(txq, skb->len); netif_txq_maybe_stop(txq, CIRC_SPACE(lp->tx_ring_head, lp->tx_ring_tail, TX_BD_NUM_MAX), --- base-commit: 8bf659bd54e1f00e34cf5244b1d289c506fa47c0 change-id: 20261013-b4-axienet-dmaengine-ring-head-ccdb8e3acb75