Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dmaengine: sun6i: Fix memory leaks

The sun6i_dma_prep_memcpy and sun6i_dma_prep_slave_sg functions were both
leaking the descriptor they allocated if an error was happening after a
successful dma_pool_alloc call.

It also fixes a memleak that was happening in the scatter gather list
traversal, that was allocating as much descriptor as there was scatter gather
items, but only freeing the current descriptor if an error was to arise.

Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>

authored by

Maxime Ripard and committed by
Vinod Koul
4fbd804e 174427c1

+12 -9
+12 -9
drivers/dma/sun6i-dma.c
··· 562 562 v_lli = dma_pool_alloc(sdev->pool, GFP_NOWAIT, &p_lli); 563 563 if (!v_lli) { 564 564 dev_err(sdev->slave.dev, "Failed to alloc lli memory\n"); 565 - kfree(txd); 566 - return NULL; 565 + goto err_txd_free; 567 566 } 568 567 569 568 ret = sun6i_dma_cfg_lli(v_lli, src, dest, len, sconfig); ··· 582 583 583 584 err_dma_free: 584 585 dma_pool_free(sdev->pool, v_lli, p_lli); 586 + err_txd_free: 587 + kfree(txd); 585 588 return NULL; 586 589 } 587 590 ··· 615 614 616 615 for_each_sg(sgl, sg, sg_len, i) { 617 616 v_lli = dma_pool_alloc(sdev->pool, GFP_NOWAIT, &p_lli); 618 - if (!v_lli) { 619 - kfree(txd); 620 - return NULL; 621 - } 617 + if (!v_lli) 618 + goto err_lli_free; 622 619 623 620 if (dir == DMA_MEM_TO_DEV) { 624 621 ret = sun6i_dma_cfg_lli(v_lli, sg_dma_address(sg), 625 622 sconfig->dst_addr, sg_dma_len(sg), 626 623 sconfig); 627 624 if (ret) 628 - goto err_dma_free; 625 + goto err_cur_lli_free; 629 626 630 627 v_lli->cfg |= DMA_CHAN_CFG_DST_IO_MODE | 631 628 DMA_CHAN_CFG_SRC_LINEAR_MODE | ··· 641 642 sg_dma_address(sg), sg_dma_len(sg), 642 643 sconfig); 643 644 if (ret) 644 - goto err_dma_free; 645 + goto err_cur_lli_free; 645 646 646 647 v_lli->cfg |= DMA_CHAN_CFG_DST_LINEAR_MODE | 647 648 DMA_CHAN_CFG_SRC_IO_MODE | ··· 664 665 665 666 return vchan_tx_prep(&vchan->vc, &txd->vd, flags); 666 667 667 - err_dma_free: 668 + err_cur_lli_free: 668 669 dma_pool_free(sdev->pool, v_lli, p_lli); 670 + err_lli_free: 671 + for (prev = txd->v_lli; prev; prev = prev->v_lli_next) 672 + dma_pool_free(sdev->pool, prev, virt_to_phys(prev)); 673 + kfree(txd); 669 674 return NULL; 670 675 } 671 676