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

mmc: moxart: Fix reference count leaks in moxart_probe

The issue happens in several error handling paths on two refcounted
object related to the object "host" (dma_chan_rx, dma_chan_tx). In
these paths, the function forgets to decrement one or both objects'
reference count increased earlier by dma_request_chan(), causing
reference count leaks.

Fix it by balancing the refcounts of both objects in some error
handling paths. In correspondence with the changes in moxart_probe(),
IS_ERR() is replaced with IS_ERR_OR_NULL() in moxart_remove() as well.

Signed-off-by: Xin Xiong <xiongx18@fudan.edu.cn>
Signed-off-by: Xiyu Yang <xiyuyang19@fudan.edu.cn>
Signed-off-by: Xin Tan <tanxin.ctf@gmail.com>
Link: https://lore.kernel.org/r/20211009041918.28419-1-xiongx18@fudan.edu.cn
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>

authored by

Xin Xiong and committed by
Ulf Hansson
8105c2ab f83c18cc

+14 -2
+14 -2
drivers/mmc/host/moxart-mmc.c
··· 621 621 ret = -EPROBE_DEFER; 622 622 goto out; 623 623 } 624 + if (!IS_ERR(host->dma_chan_tx)) { 625 + dma_release_channel(host->dma_chan_tx); 626 + host->dma_chan_tx = NULL; 627 + } 628 + if (!IS_ERR(host->dma_chan_rx)) { 629 + dma_release_channel(host->dma_chan_rx); 630 + host->dma_chan_rx = NULL; 631 + } 624 632 dev_dbg(dev, "PIO mode transfer enabled\n"); 625 633 host->have_dma = false; 626 634 } else { ··· 683 675 return 0; 684 676 685 677 out: 678 + if (!IS_ERR_OR_NULL(host->dma_chan_tx)) 679 + dma_release_channel(host->dma_chan_tx); 680 + if (!IS_ERR_OR_NULL(host->dma_chan_rx)) 681 + dma_release_channel(host->dma_chan_rx); 686 682 if (mmc) 687 683 mmc_free_host(mmc); 688 684 return ret; ··· 699 687 700 688 dev_set_drvdata(&pdev->dev, NULL); 701 689 702 - if (!IS_ERR(host->dma_chan_tx)) 690 + if (!IS_ERR_OR_NULL(host->dma_chan_tx)) 703 691 dma_release_channel(host->dma_chan_tx); 704 - if (!IS_ERR(host->dma_chan_rx)) 692 + if (!IS_ERR_OR_NULL(host->dma_chan_rx)) 705 693 dma_release_channel(host->dma_chan_rx); 706 694 mmc_remove_host(mmc); 707 695 mmc_free_host(mmc);