summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/xilinx
diff options
context:
space:
mode:
authorEsben Haabendal <esben@geanix.com>2021-06-18 12:52:23 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-06-23 14:41:30 +0200
commit6d120ab4dc39a543c6b63361e1d0541c382900a3 (patch)
treea9b96a8220c7832ce769d42f1a751e46d7aedcfe /drivers/net/ethernet/xilinx
parenta32f70e06980fd9cedfcaffaeb1d8933f6ffb9f1 (diff)
net: ll_temac: Make sure to free skb when it is completely used
commit 6aa32217a9a446275440ee8724b1ecaf1838df47 upstream. With the skb pointer piggy-backed on the TX BD, we have a simple and efficient way to free the skb buffer when the frame has been transmitted. But in order to avoid freeing the skb while there are still fragments from the skb in use, we need to piggy-back on the TX BD of the skb, not the first. Without this, we are doing use-after-free on the DMA side, when the first BD of a multi TX BD packet is seen as completed in xmit_done, and the remaining BDs are still being processed. Cc: stable@vger.kernel.org # v5.4+ Signed-off-by: Esben Haabendal <esben@geanix.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/net/ethernet/xilinx')
-rw-r--r--drivers/net/ethernet/xilinx/ll_temac_main.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c
index 5b8451c58aa4..d4b7e95a81ba 100644
--- a/drivers/net/ethernet/xilinx/ll_temac_main.c
+++ b/drivers/net/ethernet/xilinx/ll_temac_main.c
@@ -873,7 +873,6 @@ temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
return NETDEV_TX_OK;
}
cur_p->phys = cpu_to_be32(skb_dma_addr);
- ptr_to_txbd((void *)skb, cur_p);
for (ii = 0; ii < num_frag; ii++) {
if (++lp->tx_bd_tail >= TX_BD_NUM)
@@ -912,6 +911,11 @@ temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
}
cur_p->app0 |= cpu_to_be32(STS_CTRL_APP0_EOP);
+ /* Mark last fragment with skb address, so it can be consumed
+ * in temac_start_xmit_done()
+ */
+ ptr_to_txbd((void *)skb, cur_p);
+
tail_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * lp->tx_bd_tail;
lp->tx_bd_tail++;
if (lp->tx_bd_tail >= TX_BD_NUM)