Skip to content

Commit

Permalink
dmaengine: xilinx: avoid memory corruption for device_prep_dma_memcpy()
Browse files Browse the repository at this point in the history
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 <[email protected]>
Cc: Kedareswara rao Appana <[email protected]>
Cc: Michal Simek <[email protected]>
Signed-off-by: Akinobu Mita <[email protected]>
Signed-off-by: Vinod Koul <[email protected]>
  • Loading branch information
mita authored and Vinod Koul committed Mar 14, 2017
1 parent 676f9c2 commit db6a3d0
Showing 1 changed file with 2 additions and 12 deletions.
14 changes: 2 additions & 12 deletions drivers/dma/xilinx/xilinx_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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;

Expand Down

0 comments on commit db6a3d0

Please sign in to comment.