From: Akinobu Mita Date: Mon, 13 Mar 2017 15:59:12 +0000 (+0900) Subject: dmaengine: xilinx: avoid memory corruption for device_prep_dma_memcpy() X-Git-Tag: v4.12-rc1~48^2~1^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=db6a3d03e22f3daf09d8d1532bd1d3747062a561;p=platform%2Fkernel%2Flinux-exynos.git dmaengine: xilinx: avoid memory corruption for device_prep_dma_memcpy() The device_prep_dma_memcpy() callback for this driver allocates a new xilinx_dma_tx_descriptor whose TX segments list is initialized as empty, but then gets invalid TX segment pointer by list_last_entry() from the empty TX segments list and memory corruption happens by the attempt to update the next descriptor in invalid TX segment pointer. This removes unnecessary memory access for nonexistent tail TX segment which causes memory corruption. Cc: Vinod Koul Cc: Kedareswara rao Appana Cc: Michal Simek Signed-off-by: Akinobu Mita Signed-off-by: Vinod Koul --- diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c index df1676e..8cf87b1 100644 --- a/drivers/dma/xilinx/xilinx_dma.c +++ b/drivers/dma/xilinx/xilinx_dma.c @@ -1661,7 +1661,7 @@ xilinx_cdma_prep_memcpy(struct dma_chan *dchan, dma_addr_t dma_dst, { struct xilinx_dma_chan *chan = to_xilinx_chan(dchan); struct xilinx_dma_tx_descriptor *desc; - struct xilinx_cdma_tx_segment *segment, *prev; + struct xilinx_cdma_tx_segment *segment; struct xilinx_cdma_desc_hw *hw; if (!len || len > XILINX_DMA_MAX_TRANS_LEN) @@ -1688,21 +1688,11 @@ xilinx_cdma_prep_memcpy(struct dma_chan *dchan, dma_addr_t dma_dst, hw->dest_addr_msb = upper_32_bits(dma_dst); } - /* Fill the previous next descriptor with current */ - prev = list_last_entry(&desc->segments, - struct xilinx_cdma_tx_segment, node); - prev->hw.next_desc = segment->phys; - /* Insert the segment into the descriptor segments list. */ list_add_tail(&segment->node, &desc->segments); - prev = segment; - - /* Link the last hardware descriptor with the first. */ - segment = list_first_entry(&desc->segments, - struct xilinx_cdma_tx_segment, node); desc->async_tx.phys = segment->phys; - prev->hw.next_desc = segment->phys; + hw->next_desc = segment->phys; return &desc->async_tx;