Commit db6a3d03 authored by Akinobu Mita's avatar Akinobu Mita Committed by Vinod Koul

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 <vinod.koul@intel.com>
Cc: Kedareswara rao Appana <appana.durga.rao@xilinx.com>
Cc: Michal Simek <monstr@monstr.eu>
Signed-off-by: default avatarAkinobu Mita <akinobu.mita@gmail.com>
Signed-off-by: default avatarVinod Koul <vinod.koul@intel.com>
parent 676f9c26
...@@ -1661,7 +1661,7 @@ xilinx_cdma_prep_memcpy(struct dma_chan *dchan, dma_addr_t dma_dst, ...@@ -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_chan *chan = to_xilinx_chan(dchan);
struct xilinx_dma_tx_descriptor *desc; 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; struct xilinx_cdma_desc_hw *hw;
if (!len || len > XILINX_DMA_MAX_TRANS_LEN) 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, ...@@ -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); 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. */ /* Insert the segment into the descriptor segments list. */
list_add_tail(&segment->node, &desc->segments); 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; desc->async_tx.phys = segment->phys;
prev->hw.next_desc = segment->phys; hw->next_desc = segment->phys;
return &desc->async_tx; return &desc->async_tx;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment