mmc: cqhci: Fix a tiny potential memory leak on error condition
PATCH 1/1 mmc: cqhci: Fix a tiny potential memory leak on error condition
In the error case:
either cq_host->desc_base
or cq_host->trans_desc_base
might have been granted memory successfully.
The value of mmc_host->cqe_enabled stays 'false'.
Thus, cqhci_disable (mmc_cqe_ops->cqe_disable) won't be called to free the memory.
Also, cqhci_disable() is designed to disable and free all resources, not suitable to handle this corner case.
--- drivers/mmc/host/cqhci.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-)
drivers/mmc/host/cqhci.c +19 -1
@@ -223,7 +223,7 @@ static int cqhci_host_alloc_tdl(struct cqhci_host *cq_host) &cq_host->trans_desc_dma_base, GFP_KERNEL);if (!cq_host->desc_base || !cq_host->trans_desc_base) -return -ENOMEM ; + goto err_free_dma; pr_debug("%s: cqhci: desc-base: 0x%p trans-base: 0x%p\n desc_dma 0x%llx trans_dma: 0x%llx\n", mmc_hostname(cq_host->mmc), cq_host->desc_base, cq_host->trans_desc_base,
@@ -234,6 +234,24 @@ static int cqhci_host_alloc_tdl(struct cqhci_host *cq_host)setup_trans_desc (cq_host, i);return 0 ; + +err_free_dma: +if (cq_host->desc_base) { +dmam_free_coherent (mmc_dev (cq_host->mmc), cq_host->desc_size, + cq_host->desc_base, + cq_host->desc_dma_base); + cq_host->desc_base =NULL ; + cq_host->desc_dma_base =0 ; + } +if (cq_host->trans_desc_base) { +dmam_free_coherent (mmc_dev (cq_host->mmc), cq_host->data_size, + cq_host->trans_desc_base, + cq_host->trans_desc_dma_base); + cq_host->trans_desc_base =NULL ; + cq_host->trans_desc_dma_base =0 ; + } + +return -ENOMEM ; }static void __cqhci_enable (struct cqhci_host *cq_host)
Signature · 1 line
2.17.1
Adrian Hunter
maintainerQuoted 45 lines · Alamy Liu
In the error case:
either cq_host->desc_base or cq_host->trans_desc_basemight have been granted memory successfully.
The value of
mmc_host->cqe_enabledstays 'false'.
Thus,cqhci_disable(mmc_cqe_ops->cqe_disable) won't be called to free the memory.
Also,cqhci_disable()is designed to disable and free all resources, not suitable to handle this corner case.Signed-off-by Alamy Liu <[email protected]>--- drivers/mmc/host/cqhci.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-)drivers/mmc/host/cqhci.c +12
-1@@ -223,7 +223,7 @@ static int cqhci_host_alloc_tdl(struct cqhci_host *cq_host) &cq_host->trans_desc_dma_base, GFP_KERNEL);if (!cq_host->desc_base || !cq_host->trans_desc_base) -return -ENOMEM ; + goto err_free_dma; pr_debug("%s: cqhci: desc-base: 0x%p trans-base: 0x%p\n desc_dma 0x%llx trans_dma: 0x%llx\n", mmc_hostname(cq_host->mmc), cq_host->desc_base, cq_host->trans_desc_base,@@ -234,6 +234,24 @@ static int cqhci_host_alloc_tdl(struct cqhci_host *cq_host)setup_trans_desc (cq_host, i);return 0 ; + +err_free_dma: +if (cq_host->desc_base) { +dmam_free_coherent (mmc_dev (cq_host->mmc), cq_host->desc_size, + cq_host->desc_base, + cq_host->desc_dma_base); + cq_host->desc_base =NULL ; + cq_host->desc_dma_base =0 ; + } +if (cq_host->trans_desc_base) { + dmam_free_coherent(mmc_dev(cq_host->mmc), cq_host->data_size,
drivers/mmc/host/cqhci.c static int cqhci_host_alloc_tdl(struct cqhci_host *cq_host) · line 257
Quoted 10 lines
drivers/mmc/host/cqhci.c +7
-0+ cq_host->trans_desc_base, + cq_host->trans_desc_dma_base); + cq_host->trans_desc_base =NULL ; + cq_host->trans_desc_dma_base =0 ; + } + +return -ENOMEM ; }static void __cqhci_enable (struct cqhci_host *cq_host)
Normally, error handling is done step-by-step e.g.
drivers/mmc/host/cqhci.c +12 -2
@@ -217,12 +217,15 @@ static int cqhci_host_alloc_tdl(struct cqhci_host *cq_host) cq_host->desc_size, &cq_host->desc_dma_base, GFP_KERNEL); +if (!cq_host->desc_base) +return -ENOMEM ; + cq_host->trans_desc_base =dmam_alloc_coherent (mmc_dev (cq_host->mmc), cq_host->data_size, &cq_host->trans_desc_dma_base,GFP_KERNEL ); -if (!cq_host->desc_base || !cq_host->trans_desc_base) -return -ENOMEM ; +if (!cq_host->trans_desc_base) + goto err_free_dma; pr_debug("%s: cqhci: desc-base: 0x%p trans-base: 0x%p\n desc_dma 0x%llx trans_dma: 0x%llx\n", mmc_hostname(cq_host->mmc), cq_host->desc_base, cq_host->trans_desc_base,
@@ -233,6 +236,13 @@ static int cqhci_host_alloc_tdl(struct cqhci_host *cq_host)setup_trans_desc (cq_host, i);return 0 ; + +err_free_dma: +dmam_free_coherent (mmc_dev (cq_host->mmc), cq_host->desc_size, + cq_host->desc_base, cq_host->desc_dma_base); + cq_host->desc_base =NULL ; + cq_host->desc_dma_base =0 ; +return NULL ; }static void __cqhci_enable (struct cqhci_host *cq_host)
Adrian Hunter
maintainerQuoted 82 lines · Adrian Hunter
Quoted 45 lines · Alamy Liu
In the error case:
either cq_host->desc_base or cq_host->trans_desc_basemight have been granted memory successfully.
The value of
mmc_host->cqe_enabledstays 'false'.
Thus,cqhci_disable(mmc_cqe_ops->cqe_disable) won't be called to free the memory.
Also,cqhci_disable()is designed to disable and free all resources, not suitable to handle this corner case.Signed-off-by Alamy Liu <[email protected]>--- drivers/mmc/host/cqhci.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-)drivers/mmc/host/cqhci.c +12
-1@@ -223,7 +223,7 @@ static int cqhci_host_alloc_tdl(struct cqhci_host *cq_host) &cq_host->trans_desc_dma_base, GFP_KERNEL);if (!cq_host->desc_base || !cq_host->trans_desc_base) -return -ENOMEM ; + goto err_free_dma; pr_debug("%s: cqhci: desc-base: 0x%p trans-base: 0x%p\n desc_dma 0x%llx trans_dma: 0x%llx\n", mmc_hostname(cq_host->mmc), cq_host->desc_base, cq_host->trans_desc_base,@@ -234,6 +234,24 @@ static int cqhci_host_alloc_tdl(struct cqhci_host *cq_host)setup_trans_desc (cq_host, i);return 0 ; + +err_free_dma: +if (cq_host->desc_base) { +dmam_free_coherent (mmc_dev (cq_host->mmc), cq_host->desc_size, + cq_host->desc_base, + cq_host->desc_dma_base); + cq_host->desc_base =NULL ; + cq_host->desc_dma_base =0 ; + } +if (cq_host->trans_desc_base) { + dmam_free_coherent(mmc_dev(cq_host->mmc), cq_host->data_size,drivers/mmc/host/cqhci.c static int cqhci_host_alloc_tdl(struct cqhci_host *cq_host) · line 257
Quoted 10 lines
drivers/mmc/host/cqhci.c +7
-0+ cq_host->trans_desc_base, + cq_host->trans_desc_dma_base); + cq_host->trans_desc_base =NULL ; + cq_host->trans_desc_dma_base =0 ; + } + +return -ENOMEM ; }static void __cqhci_enable (struct cqhci_host *cq_host)Normally, error handling is done step-by-step e.g.
drivers/mmc/host/cqhci.c +5
-2@@ -217,12 +217,15 @@ static int cqhci_host_alloc_tdl(struct cqhci_host *cq_host) cq_host->desc_size, &cq_host->desc_dma_base, GFP_KERNEL); +if (!cq_host->desc_base) +return -ENOMEM ; + cq_host->trans_desc_base =dmam_alloc_coherent (mmc_dev (cq_host->mmc), cq_host->data_size, &cq_host->trans_desc_dma_base,GFP_KERNEL ); -if (!cq_host->desc_base || !cq_host->trans_desc_base) -return -ENOMEM ; +if (!cq_host->trans_desc_base) + goto err_free_dma; pr_debug("%s: cqhci: desc-base: 0x%p trans-base: 0x%p\n desc_dma 0x%llx trans_dma: 0x%llx\n", mmc_hostname(cq_host->mmc), cq_host->desc_base, cq_host->trans_desc_base,
drivers/mmc/host/cqhci.c static int cqhci_host_alloc_tdl(struct cqhci_host *cq_host) · line 245
Quoted 10 lines
drivers/mmc/host/cqhci.c +7
-0@@ -233,6 +236,13 @@ static int cqhci_host_alloc_tdl(struct cqhci_host *cq_host)setup_trans_desc (cq_host, i);return 0 ; + +err_free_dma: +dmam_free_coherent (mmc_dev (cq_host->mmc), cq_host->desc_size, + cq_host->desc_base, cq_host->desc_dma_base); + cq_host->desc_base =NULL ; + cq_host->desc_dma_base =0 ; +return NULL ;
That should be
return -ENOMEM;
Quoted 4 lines
drivers/mmc/host/cqhci.c +0
-0}static void __cqhci_enable (struct cqhci_host *cq_host)