From 6a9bbe53db9a5aa0be9788aa8a2c250dee55444b Mon Sep 17 00:00:00 2001 From: Ioana Radulescu Date: Wed, 14 Mar 2018 15:04:51 -0500 Subject: [PATCH] staging: fsl-dpaa2/eth: Fix incorrect kfree Use netdev_alloc_frag() instead of kmalloc to allocate space for the S/G table of egress multi-buffer frames. This fixes a bug where an unaligned pointer received from the allocator would be overwritten with the 64B aligned value, leading to a wrong address being later passed to kfree. Signed-off-by: Ioana Radulescu Reported-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c index c81a01f62fca..f013af61c447 100644 --- a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c +++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c @@ -374,12 +374,14 @@ static int build_sg_fd(struct dpaa2_eth_priv *priv, /* Prepare the HW SGT structure */ sgt_buf_size = priv->tx_data_offset + sizeof(struct dpaa2_sg_entry) * (1 + num_dma_bufs); - sgt_buf = kzalloc(sgt_buf_size + DPAA2_ETH_TX_BUF_ALIGN, GFP_ATOMIC); + sgt_buf = netdev_alloc_frag(sgt_buf_size + DPAA2_ETH_TX_BUF_ALIGN); if (unlikely(!sgt_buf)) { err = -ENOMEM; goto sgt_buf_alloc_failed; } sgt_buf = PTR_ALIGN(sgt_buf, DPAA2_ETH_TX_BUF_ALIGN); + memset(sgt_buf, 0, sgt_buf_size); + sgt = (struct dpaa2_sg_entry *)(sgt_buf + priv->tx_data_offset); /* Fill in the HW SGT structure. @@ -421,7 +423,7 @@ static int build_sg_fd(struct dpaa2_eth_priv *priv, return 0; dma_map_single_failed: - kfree(sgt_buf); + skb_free_frag(sgt_buf); sgt_buf_alloc_failed: dma_unmap_sg(dev, scl, num_sg, DMA_BIDIRECTIONAL); dma_map_sg_failed: @@ -525,9 +527,9 @@ static void free_tx_fd(const struct dpaa2_eth_priv *priv, return; } - /* Free SGT buffer kmalloc'ed on tx */ + /* Free SGT buffer allocated on tx */ if (fd_format != dpaa2_fd_single) - kfree(skbh); + skb_free_frag(skbh); /* Move on with skb release */ dev_kfree_skb(skb);